From 13cc869a4e2dec733d394c1b3e3fc7a8cc5bcf60 Mon Sep 17 00:00:00 2001 From: Celeo Date: Wed, 4 Aug 2021 20:25:39 -0700 Subject: [PATCH 01/13] feat: Add support for specifying name/path of .env This allows users to overwrite just looking for a file called .env in the working directory or its ancestors. --- src/config.rs | 31 ++++++++++++++++++++++ src/error.rs | 2 +- src/load_dotenv.rs | 64 ++++++++++++++++++++++++++++------------------ 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/config.rs b/src/config.rs index 85c8d9d43a..1423a9dc4a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -29,6 +29,8 @@ pub(crate) struct Config { pub(crate) subcommand: Subcommand, pub(crate) unsorted: bool, pub(crate) unstable: bool, + pub(crate) dotenv_filename: String, + pub(crate) dotenv_path: PathBuf, pub(crate) verbosity: Verbosity, } @@ -96,6 +98,8 @@ mod arg { pub(crate) const SHELL_COMMAND: &str = "SHELL-COMMAND"; pub(crate) const UNSORTED: &str = "UNSORTED"; pub(crate) const UNSTABLE: &str = "UNSTABLE"; + pub(crate) const DOTENV_FILENAME: &str = "DOTENV_FILENAME"; + pub(crate) const DOTENV_PATH: &str = "DOTENV_PATH"; pub(crate) const VERBOSE: &str = "VERBOSE"; pub(crate) const WORKING_DIRECTORY: &str = "WORKING-DIRECTORY"; @@ -317,6 +321,19 @@ impl Config { .long("variables") .help("List names of variables"), ) + .arg( + Arg::with_name(arg::DOTENV_FILENAME) + .long("dotenv-filename") + .takes_value(true) + .help("Load from environment file instead of .env") + .conflicts_with(arg::DOTENV_PATH), + ) + .arg( + Arg::with_name(arg::DOTENV_PATH) + .long("dotenv-path") + .help("Load from environment file at instead of ./.env") + .takes_value(true), + ) .group(ArgGroup::with_name("SUBCOMMAND").args(cmd::ALL)) .arg( Arg::with_name(arg::ARGUMENTS) @@ -537,6 +554,14 @@ impl Config { shell_args, shell_present, subcommand, + dotenv_filename: matches + .value_of(arg::DOTENV_FILENAME) + .unwrap_or(".env") + .to_owned(), + dotenv_path: matches + .value_of(arg::DOTENV_PATH) + .map(PathBuf::from) + .unwrap_or(PathBuf::new()), verbosity, }) } @@ -616,6 +641,12 @@ OPTIONS: --completions Print shell completion script for [possible values: zsh, bash, fish, powershell, elvish] + --dotenv-filename + Load from environment file instead of .env + + --dotenv-path + Load from environment file at instead of ./.env + -f, --justfile Use as justfile --list-heading Print before list --list-prefix diff --git a/src/error.rs b/src/error.rs index a60b80359d..94186c2722 100644 --- a/src/error.rs +++ b/src/error.rs @@ -426,7 +426,7 @@ impl<'src> ColorDisplay for Error<'src> { )?; }, Dotenv { dotenv_error } => { - write!(f, "Failed to load .env: {}", dotenv_error)?; + write!(f, "Failed to load environment file: {}", dotenv_error)?; }, EditorInvoke { editor, io_error } => { write!( diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index a91fbc262a..4723c5d584 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -1,43 +1,57 @@ use crate::common::*; -pub(crate) fn load_dotenv( +fn load_from_file( config: &Config, settings: &Settings, - working_directory: &Path, + path: &Path, ) -> RunResult<'static, BTreeMap> { // `dotenv::from_path_iter` should eventually be un-deprecated, see: // https://github.com/dotenv-rs/dotenv/issues/13 #![allow(deprecated)] + if settings.dotenv_load.is_none() + && config.verbosity.loud() + && !std::env::var_os("JUST_SUPPRESS_DOTENV_LOAD_WARNING") + .map(|val| val.as_os_str().to_str() == Some("1")) + .unwrap_or(false) + { + eprintln!( + "{}", + Warning::DotenvLoad.color_display(config.color.stderr()) + ); + } + + let iter = dotenv::from_path_iter(&path)?; + let mut dotenv = BTreeMap::new(); + for result in iter { + let (key, value) = result?; + if env::var_os(&key).is_none() { + dotenv.insert(key, value); + } + } + return Ok(dotenv); +} + +pub(crate) fn load_dotenv( + config: &Config, + settings: &Settings, + working_directory: &Path, +) -> RunResult<'static, BTreeMap> { if !settings.dotenv_load.unwrap_or(true) { return Ok(BTreeMap::new()); } - for directory in working_directory.ancestors() { - let path = directory.join(".env"); + // look directly for the environment file if specified by path + let path = working_directory.join(&config.dotenv_path); + if path.is_file() { + return load_from_file(config, settings, &path); + } + // search upward for the environment file if specified by filename + for directory in working_directory.ancestors() { + let path = directory.join(&config.dotenv_filename); if path.is_file() { - if settings.dotenv_load.is_none() - && config.verbosity.loud() - && !std::env::var_os("JUST_SUPPRESS_DOTENV_LOAD_WARNING") - .map(|val| val.as_os_str().to_str() == Some("1")) - .unwrap_or(false) - { - eprintln!( - "{}", - Warning::DotenvLoad.color_display(config.color.stderr()) - ); - } - - let iter = dotenv::from_path_iter(&path)?; - let mut dotenv = BTreeMap::new(); - for result in iter { - let (key, value) = result?; - if env::var_os(&key).is_none() { - dotenv.insert(key, value); - } - } - return Ok(dotenv); + return load_from_file(config, settings, &path); } } From 5fdceb0295f11e4ae4deefe1861041e076074197 Mon Sep 17 00:00:00 2001 From: Celeo Date: Wed, 4 Aug 2021 20:48:11 -0700 Subject: [PATCH 02/13] fix: resolve clippy violations --- src/config.rs | 2 +- src/load_dotenv.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 1423a9dc4a..f6697a316b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -561,7 +561,7 @@ impl Config { dotenv_path: matches .value_of(arg::DOTENV_PATH) .map(PathBuf::from) - .unwrap_or(PathBuf::new()), + .unwrap_or_default(), verbosity, }) } diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index 4723c5d584..ffdd01df66 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -29,7 +29,7 @@ fn load_from_file( dotenv.insert(key, value); } } - return Ok(dotenv); + Ok(dotenv) } pub(crate) fn load_dotenv( From e59842a687d3e7578a767187c965bcd17656f4dc Mon Sep 17 00:00:00 2001 From: Celeo Date: Wed, 4 Aug 2021 20:53:16 -0700 Subject: [PATCH 03/13] fix: update completions --- completions/just.bash | 10 +++++++++- completions/just.elvish | 2 ++ completions/just.fish | 2 ++ completions/just.powershell | 2 ++ completions/just.zsh | 2 ++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/completions/just.bash b/completions/just.bash index 56917091a5..7a1a2d279d 100644 --- a/completions/just.bash +++ b/completions/just.bash @@ -20,7 +20,7 @@ _just() { case "${cmd}" in just) - opts=" -q -u -v -e -l -h -V -f -d -c -s --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --unstable --verbose --changelog --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show ... " + opts=" -q -u -v -e -l -h -V -f -d -c -s --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --unstable --verbose --changelog --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show --dotenv-filename --dotenv-path ... " if [[ ${cur} == -* ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -97,6 +97,14 @@ _just() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --dotenv-filename) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + --dotenv-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; diff --git a/completions/just.elvish b/completions/just.elvish index 70e298686d..3425975e83 100644 --- a/completions/just.elvish +++ b/completions/just.elvish @@ -30,6 +30,8 @@ edit:completion:arg-completer[just] = [@words]{ cand --completions 'Print shell completion script for ' cand -s 'Show information about ' cand --show 'Show information about ' + cand --dotenv-filename 'Load from environment file instead of .env' + cand --dotenv-path 'Load from environment file at instead of ./.env' cand --dry-run 'Print what just would do without doing it' cand --highlight 'Highlight echoed recipe lines in bold' cand --no-dotenv 'Don''t load `.env` file' diff --git a/completions/just.fish b/completions/just.fish index 48d1da5fa8..4d50053804 100644 --- a/completions/just.fish +++ b/completions/just.fish @@ -21,6 +21,8 @@ complete -c just -n "__fish_use_subcommand" -s d -l working-directory -d 'Use ' -r -f -a "zsh bash fish powershell elvish" complete -c just -n "__fish_use_subcommand" -s s -l show -d 'Show information about ' +complete -c just -n "__fish_use_subcommand" -l dotenv-filename -d 'Load from environment file instead of .env' +complete -c just -n "__fish_use_subcommand" -l dotenv-path -d 'Load from environment file at instead of ./.env' complete -c just -n "__fish_use_subcommand" -l dry-run -d 'Print what just would do without doing it' complete -c just -n "__fish_use_subcommand" -l highlight -d 'Highlight echoed recipe lines in bold' complete -c just -n "__fish_use_subcommand" -l no-dotenv -d 'Don\'t load `.env` file' diff --git a/completions/just.powershell b/completions/just.powershell index 031d68b0ee..cef517c802 100644 --- a/completions/just.powershell +++ b/completions/just.powershell @@ -35,6 +35,8 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock { [CompletionResult]::new('--completions', 'completions', [CompletionResultType]::ParameterName, 'Print shell completion script for ') [CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Show information about ') [CompletionResult]::new('--show', 'show', [CompletionResultType]::ParameterName, 'Show information about ') + [CompletionResult]::new('--dotenv-filename', 'dotenv-filename', [CompletionResultType]::ParameterName, 'Load from environment file instead of .env') + [CompletionResult]::new('--dotenv-path', 'dotenv-path', [CompletionResultType]::ParameterName, 'Load from environment file at instead of ./.env') [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'Print what just would do without doing it') [CompletionResult]::new('--highlight', 'highlight', [CompletionResultType]::ParameterName, 'Highlight echoed recipe lines in bold') [CompletionResult]::new('--no-dotenv', 'no-dotenv', [CompletionResultType]::ParameterName, 'Don''t load `.env` file') diff --git a/completions/just.zsh b/completions/just.zsh index 25746a82b3..9be395731d 100644 --- a/completions/just.zsh +++ b/completions/just.zsh @@ -31,6 +31,8 @@ _just() { '--completions=[Print shell completion script for ]: :(zsh bash fish powershell elvish)' \ '-s+[Show information about ]: :_just_commands' \ '--show=[Show information about ]: :_just_commands' \ +'(--dotenv-path)--dotenv-filename=[Load from environment file instead of .env]' \ +'--dotenv-path=[Load from environment file at instead of ./.env]' \ '(-q --quiet)--dry-run[Print what just would do without doing it]' \ '--highlight[Highlight echoed recipe lines in bold]' \ '--no-dotenv[Don'\''t load `.env` file]' \ From 8eee06a68e36a12176026482242bf9836c70f0db Mon Sep 17 00:00:00 2001 From: Matt Boulanger Date: Thu, 5 Aug 2021 22:24:22 -0700 Subject: [PATCH 04/13] fix: Update from PR suggestions Co-authored-by: Casey Rodarmor --- src/config.rs | 8 ++++---- src/load_dotenv.rs | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/config.rs b/src/config.rs index f6697a316b..69489b13f4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -29,8 +29,8 @@ pub(crate) struct Config { pub(crate) subcommand: Subcommand, pub(crate) unsorted: bool, pub(crate) unstable: bool, - pub(crate) dotenv_filename: String, - pub(crate) dotenv_path: PathBuf, + pub(crate) dotenv_filename: Option, + pub(crate) dotenv_path: Option, pub(crate) verbosity: Verbosity, } @@ -325,13 +325,13 @@ impl Config { Arg::with_name(arg::DOTENV_FILENAME) .long("dotenv-filename") .takes_value(true) - .help("Load from environment file instead of .env") + .help("Search for environment file named instead of `.env`") .conflicts_with(arg::DOTENV_PATH), ) .arg( Arg::with_name(arg::DOTENV_PATH) .long("dotenv-path") - .help("Load from environment file at instead of ./.env") + .help("Load environment file at instead of searching for `.env` file") .takes_value(true), ) .group(ArgGroup::with_name("SUBCOMMAND").args(cmd::ALL)) diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index ffdd01df66..0ee4511101 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -41,10 +41,8 @@ pub(crate) fn load_dotenv( return Ok(BTreeMap::new()); } - // look directly for the environment file if specified by path - let path = working_directory.join(&config.dotenv_path); - if path.is_file() { - return load_from_file(config, settings, &path); + if let Some(dotenv_path) = &config.dotenv_path { + return load_from_file(config, settings, &dotenv_path); } // search upward for the environment file if specified by filename From de1bd036d7d976ff18f94f9efcbf486f26c1f54f Mon Sep 17 00:00:00 2001 From: Celeo Date: Thu, 5 Aug 2021 22:49:39 -0700 Subject: [PATCH 05/13] fix: PR suggestions and feedback --- src/config.rs | 20 ++++++----------- src/load_dotenv.rs | 56 ++++++++++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/config.rs b/src/config.rs index 69489b13f4..58ca3b71cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -29,7 +29,7 @@ pub(crate) struct Config { pub(crate) subcommand: Subcommand, pub(crate) unsorted: bool, pub(crate) unstable: bool, - pub(crate) dotenv_filename: Option, + pub(crate) dotenv_filename: Option, pub(crate) dotenv_path: Option, pub(crate) verbosity: Verbosity, } @@ -554,14 +554,8 @@ impl Config { shell_args, shell_present, subcommand, - dotenv_filename: matches - .value_of(arg::DOTENV_FILENAME) - .unwrap_or(".env") - .to_owned(), - dotenv_path: matches - .value_of(arg::DOTENV_PATH) - .map(PathBuf::from) - .unwrap_or_default(), + dotenv_filename: matches.value_of(arg::DOTENV_FILENAME).map(str::to_owned), + dotenv_path: matches.value_of(arg::DOTENV_PATH).map(PathBuf::from), verbosity, }) } @@ -642,11 +636,11 @@ OPTIONS: Print shell completion script for [possible values: zsh, bash, fish, powershell, elvish] --dotenv-filename - Load from environment file instead of .env - + Search for environment file named instead of + `.env` --dotenv-path - Load from environment file at instead of ./.env - + Load environment file at instead of searching for + `.env` file -f, --justfile Use as justfile --list-heading Print before list --list-prefix diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index 0ee4511101..852fd7d777 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -1,5 +1,35 @@ use crate::common::*; +const DEFAULT_DOTENV_FILENAME: &str = ".env"; + +pub(crate) fn load_dotenv( + config: &Config, + settings: &Settings, + working_directory: &Path, +) -> RunResult<'static, BTreeMap> { + if !settings.dotenv_load.unwrap_or(true) { + return Ok(BTreeMap::new()); + } + + if let Some(path) = &config.dotenv_path { + return load_from_file(config, settings, &path); + } + + let filename = match &config.dotenv_filename { + Some(name) => name, + None => DEFAULT_DOTENV_FILENAME, + }; + + for directory in working_directory.ancestors() { + let path = directory.join(&filename); + if path.is_file() { + return load_from_file(config, settings, &path); + } + } + + Ok(BTreeMap::new()) +} + fn load_from_file( config: &Config, settings: &Settings, @@ -11,6 +41,8 @@ fn load_from_file( if settings.dotenv_load.is_none() && config.verbosity.loud() + && config.dotenv_filename.is_none() + && config.dotenv_path.is_none() && !std::env::var_os("JUST_SUPPRESS_DOTENV_LOAD_WARNING") .map(|val| val.as_os_str().to_str() == Some("1")) .unwrap_or(false) @@ -31,27 +63,3 @@ fn load_from_file( } Ok(dotenv) } - -pub(crate) fn load_dotenv( - config: &Config, - settings: &Settings, - working_directory: &Path, -) -> RunResult<'static, BTreeMap> { - if !settings.dotenv_load.unwrap_or(true) { - return Ok(BTreeMap::new()); - } - - if let Some(dotenv_path) = &config.dotenv_path { - return load_from_file(config, settings, &dotenv_path); - } - - // search upward for the environment file if specified by filename - for directory in working_directory.ancestors() { - let path = directory.join(&config.dotenv_filename); - if path.is_file() { - return load_from_file(config, settings, &path); - } - } - - Ok(BTreeMap::new()) -} From e85ae7d7f0f64bbe1e452651ec70aa1eb3aed01b Mon Sep 17 00:00:00 2001 From: Celeo Date: Thu, 5 Aug 2021 22:51:38 -0700 Subject: [PATCH 06/13] fix: update completions --- completions/just.elvish | 4 ++-- completions/just.fish | 4 ++-- completions/just.powershell | 4 ++-- completions/just.zsh | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/completions/just.elvish b/completions/just.elvish index 3425975e83..d71c7921d5 100644 --- a/completions/just.elvish +++ b/completions/just.elvish @@ -30,8 +30,8 @@ edit:completion:arg-completer[just] = [@words]{ cand --completions 'Print shell completion script for ' cand -s 'Show information about ' cand --show 'Show information about ' - cand --dotenv-filename 'Load from environment file instead of .env' - cand --dotenv-path 'Load from environment file at instead of ./.env' + cand --dotenv-filename 'Search for environment file named instead of `.env`' + cand --dotenv-path 'Load environment file at instead of searching for `.env` file' cand --dry-run 'Print what just would do without doing it' cand --highlight 'Highlight echoed recipe lines in bold' cand --no-dotenv 'Don''t load `.env` file' diff --git a/completions/just.fish b/completions/just.fish index 4d50053804..91c7df6fd8 100644 --- a/completions/just.fish +++ b/completions/just.fish @@ -21,8 +21,8 @@ complete -c just -n "__fish_use_subcommand" -s d -l working-directory -d 'Use ' -r -f -a "zsh bash fish powershell elvish" complete -c just -n "__fish_use_subcommand" -s s -l show -d 'Show information about ' -complete -c just -n "__fish_use_subcommand" -l dotenv-filename -d 'Load from environment file instead of .env' -complete -c just -n "__fish_use_subcommand" -l dotenv-path -d 'Load from environment file at instead of ./.env' +complete -c just -n "__fish_use_subcommand" -l dotenv-filename -d 'Search for environment file named instead of `.env`' +complete -c just -n "__fish_use_subcommand" -l dotenv-path -d 'Load environment file at instead of searching for `.env` file' complete -c just -n "__fish_use_subcommand" -l dry-run -d 'Print what just would do without doing it' complete -c just -n "__fish_use_subcommand" -l highlight -d 'Highlight echoed recipe lines in bold' complete -c just -n "__fish_use_subcommand" -l no-dotenv -d 'Don\'t load `.env` file' diff --git a/completions/just.powershell b/completions/just.powershell index cef517c802..596c4c794c 100644 --- a/completions/just.powershell +++ b/completions/just.powershell @@ -35,8 +35,8 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock { [CompletionResult]::new('--completions', 'completions', [CompletionResultType]::ParameterName, 'Print shell completion script for ') [CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Show information about ') [CompletionResult]::new('--show', 'show', [CompletionResultType]::ParameterName, 'Show information about ') - [CompletionResult]::new('--dotenv-filename', 'dotenv-filename', [CompletionResultType]::ParameterName, 'Load from environment file instead of .env') - [CompletionResult]::new('--dotenv-path', 'dotenv-path', [CompletionResultType]::ParameterName, 'Load from environment file at instead of ./.env') + [CompletionResult]::new('--dotenv-filename', 'dotenv-filename', [CompletionResultType]::ParameterName, 'Search for environment file named instead of `.env`') + [CompletionResult]::new('--dotenv-path', 'dotenv-path', [CompletionResultType]::ParameterName, 'Load environment file at instead of searching for `.env` file') [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'Print what just would do without doing it') [CompletionResult]::new('--highlight', 'highlight', [CompletionResultType]::ParameterName, 'Highlight echoed recipe lines in bold') [CompletionResult]::new('--no-dotenv', 'no-dotenv', [CompletionResultType]::ParameterName, 'Don''t load `.env` file') diff --git a/completions/just.zsh b/completions/just.zsh index 9be395731d..0f0c8fb868 100644 --- a/completions/just.zsh +++ b/completions/just.zsh @@ -31,8 +31,8 @@ _just() { '--completions=[Print shell completion script for ]: :(zsh bash fish powershell elvish)' \ '-s+[Show information about ]: :_just_commands' \ '--show=[Show information about ]: :_just_commands' \ -'(--dotenv-path)--dotenv-filename=[Load from environment file instead of .env]' \ -'--dotenv-path=[Load from environment file at instead of ./.env]' \ +'(--dotenv-path)--dotenv-filename=[Search for environment file named instead of `.env`]' \ +'--dotenv-path=[Load environment file at instead of searching for `.env` file]' \ '(-q --quiet)--dry-run[Print what just would do without doing it]' \ '--highlight[Highlight echoed recipe lines in bold]' \ '--no-dotenv[Don'\''t load `.env` file]' \ From 1ca5d5993a2a4f701c8dc64c44d4766b3ba694ff Mon Sep 17 00:00:00 2001 From: Celeo Date: Thu, 5 Aug 2021 23:27:00 -0700 Subject: [PATCH 07/13] fix: adding tests for new dotenv flags --- src/config.rs | 5 +++++ tests/dotenv.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/config.rs b/src/config.rs index 58ca3b71cb..78dc6adbba 100644 --- a/src/config.rs +++ b/src/config.rs @@ -908,6 +908,11 @@ ARGS: verbosity: Verbosity::Quiet, } + error! { + name: dotenv_both_filename_and_path, + args: ["--dotenv-filename", "foo", "--dotenv-path", "bar"], + } + test! { name: set_default, args: [], diff --git a/tests/dotenv.rs b/tests/dotenv.rs index 666a04b16a..b78ea46030 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -101,3 +101,41 @@ echo $DOTENV_KEY .suppress_dotenv_load_warning(false) .run(); } + +#[test] +fn path_not_found() { + Test::new() + .justfile("foo:\n\techo $NAME") + .args(&["--dotenv-path", ".env.prod"]) + .stderr("error: Failed to load environment file: No such file or directory (os error 2)\n") + .status(EXIT_FAILURE) + .run(); +} + +#[test] +fn path_resolves() { + Test::new() + .justfile("foo:\n\t#!/bin/bash\n\techo $NAME") + .tree(tree! { + subdir: { + ".env": "NAME=bar" + } + }) + .args(&["--dotenv-path", "subdir/.env"]) + .stdout("bar\n") + .status(EXIT_SUCCESS) + .run(); +} + +#[test] +fn filename_resolves() { + Test::new() + .justfile("foo:\n\t#!/bin/bash\n\techo $NAME") + .tree(tree! { + ".env.special": "NAME=bar" + }) + .args(&["--dotenv-filename", ".env.special"]) + .stdout("bar\n") + .status(EXIT_SUCCESS) + .run(); +} From da5cbbb8d1eeaa48e3ea33a2bf266901bf79d23b Mon Sep 17 00:00:00 2001 From: Celeo Date: Fri, 6 Aug 2021 08:44:03 -0700 Subject: [PATCH 08/13] fix: fix failing test on windows --- tests/dotenv.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/dotenv.rs b/tests/dotenv.rs index b78ea46030..fe5eb1cd7f 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -107,7 +107,11 @@ fn path_not_found() { Test::new() .justfile("foo:\n\techo $NAME") .args(&["--dotenv-path", ".env.prod"]) - .stderr("error: Failed to load environment file: No such file or directory (os error 2)\n") + .stderr(if cfg!(windows) { + "error: Failed to load environment file: The system cannot find the file specified. (os error 2)\n" + } else { + "error: Failed to load environment file: No such file or directory (os error 2)\n" + }) .status(EXIT_FAILURE) .run(); } From 0b79075b011754e3238170cb9e7c038829445708 Mon Sep 17 00:00:00 2001 From: Celeo Date: Fri, 6 Aug 2021 08:55:50 -0700 Subject: [PATCH 09/13] fix: correct formatting --- tests/dotenv.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/dotenv.rs b/tests/dotenv.rs index fe5eb1cd7f..0991aed3aa 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -108,7 +108,8 @@ fn path_not_found() { .justfile("foo:\n\techo $NAME") .args(&["--dotenv-path", ".env.prod"]) .stderr(if cfg!(windows) { - "error: Failed to load environment file: The system cannot find the file specified. (os error 2)\n" + "error: Failed to load environment file: The system cannot find the file specified. (os \ + error 2)\n" } else { "error: Failed to load environment file: No such file or directory (os error 2)\n" }) From 56a6320a8c921ab5b16f9569983a7baf94f48c3f Mon Sep 17 00:00:00 2001 From: Matt Boulanger Date: Sat, 7 Aug 2021 19:19:39 -0700 Subject: [PATCH 10/13] fix: apply suggestions from code review Co-authored-by: Casey Rodarmor --- src/config.rs | 2 +- src/load_dotenv.rs | 9 +++------ tests/dotenv.rs | 5 ++++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/config.rs b/src/config.rs index 78dc6adbba..592131223f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -331,7 +331,7 @@ impl Config { .arg( Arg::with_name(arg::DOTENV_PATH) .long("dotenv-path") - .help("Load environment file at instead of searching for `.env` file") + .help("Load environment file at instead of searching for one") .takes_value(true), ) .group(ArgGroup::with_name("SUBCOMMAND").args(cmd::ALL)) diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index 852fd7d777..96c7c80bfa 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -15,10 +15,7 @@ pub(crate) fn load_dotenv( return load_from_file(config, settings, &path); } - let filename = match &config.dotenv_filename { - Some(name) => name, - None => DEFAULT_DOTENV_FILENAME, - }; + let filename = config.dotenv_filename.unwrap_or(DEFAULT_DOTENV_FILENAME); for directory in working_directory.ancestors() { let path = directory.join(&filename); @@ -39,8 +36,8 @@ fn load_from_file( // https://github.com/dotenv-rs/dotenv/issues/13 #![allow(deprecated)] - if settings.dotenv_load.is_none() - && config.verbosity.loud() + if config.verbosity.loud() + && settings.dotenv_load.is_none() && config.dotenv_filename.is_none() && config.dotenv_path.is_none() && !std::env::var_os("JUST_SUPPRESS_DOTENV_LOAD_WARNING") diff --git a/tests/dotenv.rs b/tests/dotenv.rs index 0991aed3aa..c78eacf29e 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -105,7 +105,10 @@ echo $DOTENV_KEY #[test] fn path_not_found() { Test::new() - .justfile("foo:\n\techo $NAME") + .justfile(" + foo: + echo $NAME + ") .args(&["--dotenv-path", ".env.prod"]) .stderr(if cfg!(windows) { "error: Failed to load environment file: The system cannot find the file specified. (os \ From 5427d03676d45e5e3ee5be1bca14bf3aeeba1e61 Mon Sep 17 00:00:00 2001 From: Celeo Date: Sat, 7 Aug 2021 19:31:40 -0700 Subject: [PATCH 11/13] fix: PR suggestions --- completions/just.elvish | 2 +- completions/just.fish | 2 +- completions/just.powershell | 2 +- completions/just.zsh | 2 +- src/config.rs | 4 ++-- src/load_dotenv.rs | 6 +++++- tests/dotenv.rs | 22 ++++++++++++++++++---- 7 files changed, 29 insertions(+), 11 deletions(-) diff --git a/completions/just.elvish b/completions/just.elvish index d71c7921d5..4972a56e49 100644 --- a/completions/just.elvish +++ b/completions/just.elvish @@ -31,7 +31,7 @@ edit:completion:arg-completer[just] = [@words]{ cand -s 'Show information about ' cand --show 'Show information about ' cand --dotenv-filename 'Search for environment file named instead of `.env`' - cand --dotenv-path 'Load environment file at instead of searching for `.env` file' + cand --dotenv-path 'Load environment file at instead of searching for one' cand --dry-run 'Print what just would do without doing it' cand --highlight 'Highlight echoed recipe lines in bold' cand --no-dotenv 'Don''t load `.env` file' diff --git a/completions/just.fish b/completions/just.fish index 91c7df6fd8..5379aeafa5 100644 --- a/completions/just.fish +++ b/completions/just.fish @@ -22,7 +22,7 @@ complete -c just -n "__fish_use_subcommand" -s c -l command -d 'Run an arbitrary complete -c just -n "__fish_use_subcommand" -l completions -d 'Print shell completion script for ' -r -f -a "zsh bash fish powershell elvish" complete -c just -n "__fish_use_subcommand" -s s -l show -d 'Show information about ' complete -c just -n "__fish_use_subcommand" -l dotenv-filename -d 'Search for environment file named instead of `.env`' -complete -c just -n "__fish_use_subcommand" -l dotenv-path -d 'Load environment file at instead of searching for `.env` file' +complete -c just -n "__fish_use_subcommand" -l dotenv-path -d 'Load environment file at instead of searching for one' complete -c just -n "__fish_use_subcommand" -l dry-run -d 'Print what just would do without doing it' complete -c just -n "__fish_use_subcommand" -l highlight -d 'Highlight echoed recipe lines in bold' complete -c just -n "__fish_use_subcommand" -l no-dotenv -d 'Don\'t load `.env` file' diff --git a/completions/just.powershell b/completions/just.powershell index 596c4c794c..f2be312770 100644 --- a/completions/just.powershell +++ b/completions/just.powershell @@ -36,7 +36,7 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock { [CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Show information about ') [CompletionResult]::new('--show', 'show', [CompletionResultType]::ParameterName, 'Show information about ') [CompletionResult]::new('--dotenv-filename', 'dotenv-filename', [CompletionResultType]::ParameterName, 'Search for environment file named instead of `.env`') - [CompletionResult]::new('--dotenv-path', 'dotenv-path', [CompletionResultType]::ParameterName, 'Load environment file at instead of searching for `.env` file') + [CompletionResult]::new('--dotenv-path', 'dotenv-path', [CompletionResultType]::ParameterName, 'Load environment file at instead of searching for one') [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'Print what just would do without doing it') [CompletionResult]::new('--highlight', 'highlight', [CompletionResultType]::ParameterName, 'Highlight echoed recipe lines in bold') [CompletionResult]::new('--no-dotenv', 'no-dotenv', [CompletionResultType]::ParameterName, 'Don''t load `.env` file') diff --git a/completions/just.zsh b/completions/just.zsh index 0f0c8fb868..b504b709a7 100644 --- a/completions/just.zsh +++ b/completions/just.zsh @@ -32,7 +32,7 @@ _just() { '-s+[Show information about ]: :_just_commands' \ '--show=[Show information about ]: :_just_commands' \ '(--dotenv-path)--dotenv-filename=[Search for environment file named instead of `.env`]' \ -'--dotenv-path=[Load environment file at instead of searching for `.env` file]' \ +'--dotenv-path=[Load environment file at instead of searching for one]' \ '(-q --quiet)--dry-run[Print what just would do without doing it]' \ '--highlight[Highlight echoed recipe lines in bold]' \ '--no-dotenv[Don'\''t load `.env` file]' \ diff --git a/src/config.rs b/src/config.rs index 592131223f..cc7e441b67 100644 --- a/src/config.rs +++ b/src/config.rs @@ -639,8 +639,8 @@ OPTIONS: Search for environment file named instead of `.env` --dotenv-path - Load environment file at instead of searching for - `.env` file + Load environment file at instead of searching for one + -f, --justfile Use as justfile --list-heading Print before list --list-prefix diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index 96c7c80bfa..e825181e36 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -15,7 +15,11 @@ pub(crate) fn load_dotenv( return load_from_file(config, settings, &path); } - let filename = config.dotenv_filename.unwrap_or(DEFAULT_DOTENV_FILENAME); + let filename = config + .dotenv_filename + .as_deref() + .unwrap_or(DEFAULT_DOTENV_FILENAME) + .to_owned(); for directory in working_directory.ancestors() { let path = directory.join(&filename); diff --git a/tests/dotenv.rs b/tests/dotenv.rs index c78eacf29e..652d18f254 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -105,10 +105,12 @@ echo $DOTENV_KEY #[test] fn path_not_found() { Test::new() - .justfile(" + .justfile( + " foo: echo $NAME - ") + ", + ) .args(&["--dotenv-path", ".env.prod"]) .stderr(if cfg!(windows) { "error: Failed to load environment file: The system cannot find the file specified. (os \ @@ -123,7 +125,13 @@ fn path_not_found() { #[test] fn path_resolves() { Test::new() - .justfile("foo:\n\t#!/bin/bash\n\techo $NAME") + .justfile( + " + foo: + #!/bin/bash + echo $NAME + ", + ) .tree(tree! { subdir: { ".env": "NAME=bar" @@ -138,7 +146,13 @@ fn path_resolves() { #[test] fn filename_resolves() { Test::new() - .justfile("foo:\n\t#!/bin/bash\n\techo $NAME") + .justfile( + " + foo: + #!/bin/bash + echo $NAME + ", + ) .tree(tree! { ".env.special": "NAME=bar" }) From 6f6e50970181e2ae34134cc8dece044dd18471f6 Mon Sep 17 00:00:00 2001 From: Celeo Date: Sun, 8 Aug 2021 21:53:36 -0700 Subject: [PATCH 12/13] fix: override dotenv-load for new cli flags --- src/load_dotenv.rs | 5 ++++- tests/dotenv.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/load_dotenv.rs b/src/load_dotenv.rs index e825181e36..c9449261b4 100644 --- a/src/load_dotenv.rs +++ b/src/load_dotenv.rs @@ -7,7 +7,10 @@ pub(crate) fn load_dotenv( settings: &Settings, working_directory: &Path, ) -> RunResult<'static, BTreeMap> { - if !settings.dotenv_load.unwrap_or(true) { + if !settings.dotenv_load.unwrap_or(true) + && config.dotenv_filename.is_none() + && config.dotenv_path.is_none() + { return Ok(BTreeMap::new()); } diff --git a/tests/dotenv.rs b/tests/dotenv.rs index 652d18f254..dae29d21b7 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -161,3 +161,47 @@ fn filename_resolves() { .status(EXIT_SUCCESS) .run(); } + +#[test] +fn filename_flag_overwrites_no_load() { + Test::new() + .justfile( + " + set dotenv-load := false + + foo: + #!/bin/bash + echo $NAME + ", + ) + .tree(tree! { + ".env.special": "NAME=bar" + }) + .args(&["--dotenv-filename", ".env.special"]) + .stdout("bar\n") + .status(EXIT_SUCCESS) + .run(); +} + +#[test] +fn path_flag_overwrites_no_load() { + Test::new() + .justfile( + " + set dotenv-load := false + + foo: + #!/bin/bash + echo $NAME + ", + ) + .tree(tree! { + subdir: { + ".env": "NAME=bar" + } + }) + .args(&["--dotenv-path", "subdir/.env"]) + .stdout("bar\n") + .status(EXIT_SUCCESS) + .run(); +} From 3e43b49b76abd62b77e6e34e03c0c673f995eb06 Mon Sep 17 00:00:00 2001 From: Celeo Date: Sun, 8 Aug 2021 22:29:20 -0700 Subject: [PATCH 13/13] fix: remove bash line from tests --- tests/dotenv.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/dotenv.rs b/tests/dotenv.rs index dae29d21b7..6078268074 100644 --- a/tests/dotenv.rs +++ b/tests/dotenv.rs @@ -128,8 +128,7 @@ fn path_resolves() { .justfile( " foo: - #!/bin/bash - echo $NAME + @echo $NAME ", ) .tree(tree! { @@ -149,8 +148,7 @@ fn filename_resolves() { .justfile( " foo: - #!/bin/bash - echo $NAME + @echo $NAME ", ) .tree(tree! { @@ -170,8 +168,7 @@ fn filename_flag_overwrites_no_load() { set dotenv-load := false foo: - #!/bin/bash - echo $NAME + @echo $NAME ", ) .tree(tree! { @@ -191,8 +188,7 @@ fn path_flag_overwrites_no_load() { set dotenv-load := false foo: - #!/bin/bash - echo $NAME + @echo $NAME ", ) .tree(tree! {