Add dotenv-load
setting (#778)
The `dotenv-load` setting controls whether or not a `.env` file will be loaded if present. It currently defaults to true.
This commit is contained in:
parent
2e8c58e1cd
commit
18b9799e8d
@ -55,9 +55,12 @@ assignment : NAME ':=' expression eol
|
|||||||
|
|
||||||
export : 'export' assignment
|
export : 'export' assignment
|
||||||
|
|
||||||
setting : 'set' 'export'
|
setting : 'set' 'dotenv-load' boolean?
|
||||||
|
| 'set' 'export' boolean?
|
||||||
| 'set' 'shell' ':=' '[' string (',' string)* ','? ']'
|
| 'set' 'shell' ':=' '[' string (',' string)* ','? ']'
|
||||||
|
|
||||||
|
boolean : ':=' ('true' | 'false')
|
||||||
|
|
||||||
expression : 'if' condition '{' expression '}' else '{' expression '}'
|
expression : 'if' condition '{' expression '}' else '{' expression '}'
|
||||||
| value '+' expression
|
| value '+' expression
|
||||||
| value
|
| value
|
||||||
|
47
README.adoc
47
README.adoc
@ -388,29 +388,30 @@ foo:
|
|||||||
[options="header"]
|
[options="header"]
|
||||||
|=================
|
|=================
|
||||||
| Name | Value | Description
|
| Name | Value | Description
|
||||||
| `export` | | Export all variables as environment variables
|
| `dotenv-load` | `true` or `false` | Load a `.env` file, if present.
|
||||||
|
| `export` | `true` or `false` | Export all variables as environment variables.
|
||||||
|`shell` | `[COMMAND, ARGS...]` | Set the command used to invoke recipes and evaluate backticks.
|
|`shell` | `[COMMAND, ARGS...]` | Set the command used to invoke recipes and evaluate backticks.
|
||||||
|=================
|
|=================
|
||||||
|
|
||||||
==== Shell
|
Boolean settings can be written as:
|
||||||
|
|
||||||
The `shell` setting controls the command used to invoke recipe lines and backticks. Shebang recipes are unaffected.
|
|
||||||
|
|
||||||
```make
|
|
||||||
# use python3 to execute recipe lines and backticks
|
|
||||||
set shell := ["python3", "-c"]
|
|
||||||
|
|
||||||
# use print to capture result of evaluation
|
|
||||||
foos := `print("foo" * 4)`
|
|
||||||
|
|
||||||
foo:
|
|
||||||
print("Snake snake snake snake.")
|
|
||||||
print("{{foos}}")
|
|
||||||
```
|
```
|
||||||
|
set NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
Which is equivalent to:
|
||||||
|
|
||||||
|
```
|
||||||
|
set NAME := true
|
||||||
|
```
|
||||||
|
|
||||||
|
==== Dotenv Load
|
||||||
|
|
||||||
|
If `dotenv-load` is `true`, a `.env` file will be loaded if present. Defaults to `true`.
|
||||||
|
|
||||||
==== Export
|
==== Export
|
||||||
|
|
||||||
The `export` setting causes all Just variables to be exported as environment variables.
|
The `export` setting causes all Just variables to be exported as environment variables. Defaults to `false`.
|
||||||
|
|
||||||
```make
|
```make
|
||||||
set export
|
set export
|
||||||
@ -428,6 +429,22 @@ hello
|
|||||||
goodbye
|
goodbye
|
||||||
```
|
```
|
||||||
|
|
||||||
|
==== Shell
|
||||||
|
|
||||||
|
The `shell` setting controls the command used to invoke recipe lines and backticks. Shebang recipes are unaffected.
|
||||||
|
|
||||||
|
```make
|
||||||
|
# use python3 to execute recipe lines and backticks
|
||||||
|
set shell := ["python3", "-c"]
|
||||||
|
|
||||||
|
# use print to capture result of evaluation
|
||||||
|
foos := `print("foo" * 4)`
|
||||||
|
|
||||||
|
foo:
|
||||||
|
print("Snake snake snake snake.")
|
||||||
|
print("{{foos}}")
|
||||||
|
```
|
||||||
|
|
||||||
=== Documentation Comments
|
=== Documentation Comments
|
||||||
|
|
||||||
Comments immediately preceding a recipe will appear in `just --list`:
|
Comments immediately preceding a recipe will appear in `just --list`:
|
||||||
|
@ -65,13 +65,16 @@ impl<'src> Analyzer<'src> {
|
|||||||
|
|
||||||
for (_, set) in self.sets {
|
for (_, set) in self.sets {
|
||||||
match set.value {
|
match set.value {
|
||||||
|
Setting::DotenvLoad(dotenv_load) => {
|
||||||
|
settings.dotenv_load = dotenv_load;
|
||||||
|
},
|
||||||
|
Setting::Export(export) => {
|
||||||
|
settings.export = export;
|
||||||
|
},
|
||||||
Setting::Shell(shell) => {
|
Setting::Shell(shell) => {
|
||||||
assert!(settings.shell.is_none());
|
assert!(settings.shell.is_none());
|
||||||
settings.shell = Some(shell);
|
settings.shell = Some(shell);
|
||||||
},
|
},
|
||||||
Setting::Export => {
|
|
||||||
settings.export = true;
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ impl Display for CompilationError<'_> {
|
|||||||
|
|
||||||
write!(f, "{}", message.prefix())?;
|
write!(f, "{}", message.prefix())?;
|
||||||
|
|
||||||
match self.kind {
|
match &self.kind {
|
||||||
AliasShadowsRecipe { alias, recipe_line } => {
|
AliasShadowsRecipe { alias, recipe_line } => {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
@ -116,22 +116,23 @@ impl Display for CompilationError<'_> {
|
|||||||
"Dependency `{}` got {} {} but takes ",
|
"Dependency `{}` got {} {} but takes ",
|
||||||
dependency,
|
dependency,
|
||||||
found,
|
found,
|
||||||
Count("argument", found),
|
Count("argument", *found),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if min == max {
|
if min == max {
|
||||||
let expected = min;
|
let expected = min;
|
||||||
writeln!(f, "{} {}", expected, Count("argument", expected))?;
|
writeln!(f, "{} {}", expected, Count("argument", *expected))?;
|
||||||
} else if found < min {
|
} else if found < min {
|
||||||
writeln!(f, "at least {} {}", min, Count("argument", min))?;
|
writeln!(f, "at least {} {}", min, Count("argument", *min))?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, "at most {} {}", max, Count("argument", max))?;
|
writeln!(f, "at most {} {}", max, Count("argument", *max))?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExpectedKeyword { expected, found } => writeln!(
|
ExpectedKeyword { expected, found } => writeln!(
|
||||||
f,
|
f,
|
||||||
"Expected keyword `{}` but found identifier `{}`",
|
"Expected keyword {} but found identifier `{}`",
|
||||||
expected, found
|
List::or_ticked(expected),
|
||||||
|
found
|
||||||
)?,
|
)?,
|
||||||
ParameterShadowsVariable { parameter } => {
|
ParameterShadowsVariable { parameter } => {
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -171,7 +172,7 @@ impl Display for CompilationError<'_> {
|
|||||||
"Function `{}` called with {} {} but takes {}",
|
"Function `{}` called with {} {} but takes {}",
|
||||||
function,
|
function,
|
||||||
found,
|
found,
|
||||||
Count("argument", found),
|
Count("argument", *found),
|
||||||
expected
|
expected
|
||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,7 @@ pub(crate) enum CompilationErrorKind<'src> {
|
|||||||
first: usize,
|
first: usize,
|
||||||
},
|
},
|
||||||
ExpectedKeyword {
|
ExpectedKeyword {
|
||||||
expected: Keyword,
|
expected: Vec<Keyword>,
|
||||||
found: &'src str,
|
found: &'src str,
|
||||||
},
|
},
|
||||||
ExtraLeadingWhitespace,
|
ExtraLeadingWhitespace,
|
||||||
|
@ -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)?
|
load_dotenv(&search.working_directory, &self.settings)?
|
||||||
} else {
|
} else {
|
||||||
BTreeMap::new()
|
BTreeMap::new()
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,9 @@ pub(crate) enum Keyword {
|
|||||||
Alias,
|
Alias,
|
||||||
Else,
|
Else,
|
||||||
Export,
|
Export,
|
||||||
|
DotenvLoad,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
If,
|
If,
|
||||||
Set,
|
Set,
|
||||||
Shell,
|
Shell,
|
||||||
|
@ -2,10 +2,16 @@ use crate::common::*;
|
|||||||
|
|
||||||
pub(crate) fn load_dotenv(
|
pub(crate) fn load_dotenv(
|
||||||
working_directory: &Path,
|
working_directory: &Path,
|
||||||
|
settings: &Settings,
|
||||||
) -> 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 {
|
||||||
|
return Ok(BTreeMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
for directory in working_directory.ancestors() {
|
for directory in working_directory.ancestors() {
|
||||||
let path = directory.join(".env");
|
let path = directory.join(".env");
|
||||||
|
|
||||||
|
@ -187,17 +187,17 @@ impl<'src> Node<'src> for Set<'src> {
|
|||||||
fn tree(&self) -> Tree<'src> {
|
fn tree(&self) -> Tree<'src> {
|
||||||
let mut set = Tree::atom(Keyword::Set.lexeme());
|
let mut set = Tree::atom(Keyword::Set.lexeme());
|
||||||
|
|
||||||
set.push_mut(self.name.lexeme());
|
set.push_mut(self.name.lexeme().replace('-', "_"));
|
||||||
|
|
||||||
use Setting::*;
|
use Setting::*;
|
||||||
match &self.value {
|
match &self.value {
|
||||||
|
DotenvLoad(value) | Export(value) => set.push_mut(value.to_string()),
|
||||||
Shell(setting::Shell { command, arguments }) => {
|
Shell(setting::Shell { command, arguments }) => {
|
||||||
set.push_mut(Tree::string(&command.cooked));
|
set.push_mut(Tree::string(&command.cooked));
|
||||||
for argument in arguments {
|
for argument in arguments {
|
||||||
set.push_mut(Tree::string(&argument.cooked));
|
set.push_mut(Tree::string(&argument.cooked));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Export => {},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
|
@ -179,7 +179,10 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
if expected == found {
|
if expected == found {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(identifier.error(CompilationErrorKind::ExpectedKeyword { expected, found }))
|
Err(identifier.error(CompilationErrorKind::ExpectedKeyword {
|
||||||
|
expected: vec![expected],
|
||||||
|
found,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +350,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
Some(Keyword::Set) =>
|
Some(Keyword::Set) =>
|
||||||
if self.next_are(&[Identifier, Identifier, ColonEquals])
|
if self.next_are(&[Identifier, Identifier, ColonEquals])
|
||||||
|| self.next_are(&[Identifier, Identifier, Eol])
|
|| self.next_are(&[Identifier, Identifier, Eol])
|
||||||
|
|| self.next_are(&[Identifier, Identifier, Eof])
|
||||||
{
|
{
|
||||||
items.push(Item::Set(self.parse_set()?));
|
items.push(Item::Set(self.parse_set()?));
|
||||||
} else {
|
} else {
|
||||||
@ -678,19 +682,50 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
Ok(lines)
|
Ok(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a boolean setting value
|
||||||
|
fn parse_set_bool(&mut self) -> CompilationResult<'src, bool> {
|
||||||
|
if !self.accepted(ColonEquals)? {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let identifier = self.expect(Identifier)?;
|
||||||
|
|
||||||
|
let value = if Keyword::True == identifier.lexeme() {
|
||||||
|
true
|
||||||
|
} else if Keyword::False == identifier.lexeme() {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
return Err(identifier.error(CompilationErrorKind::ExpectedKeyword {
|
||||||
|
expected: vec![Keyword::True, Keyword::False],
|
||||||
|
found: identifier.lexeme(),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a setting
|
/// Parse a setting
|
||||||
fn parse_set(&mut self) -> CompilationResult<'src, Set<'src>> {
|
fn parse_set(&mut self) -> CompilationResult<'src, Set<'src>> {
|
||||||
self.presume_keyword(Keyword::Set)?;
|
self.presume_keyword(Keyword::Set)?;
|
||||||
let name = Name::from_identifier(self.presume(Identifier)?);
|
let name = Name::from_identifier(self.presume(Identifier)?);
|
||||||
|
let lexeme = name.lexeme();
|
||||||
|
|
||||||
if name.lexeme() == Keyword::Export.lexeme() {
|
if Keyword::DotenvLoad == lexeme {
|
||||||
|
let value = self.parse_set_bool()?;
|
||||||
return Ok(Set {
|
return Ok(Set {
|
||||||
value: Setting::Export,
|
value: Setting::DotenvLoad(value),
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
} else if Keyword::Export == lexeme {
|
||||||
|
let value = self.parse_set_bool()?;
|
||||||
|
return Ok(Set {
|
||||||
|
value: Setting::Export(value),
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.presume(ColonEquals)?;
|
self.expect(ColonEquals)?;
|
||||||
|
|
||||||
if name.lexeme() == Keyword::Shell.lexeme() {
|
if name.lexeme() == Keyword::Shell.lexeme() {
|
||||||
self.expect(BracketL)?;
|
self.expect(BracketL)?;
|
||||||
|
|
||||||
@ -1541,6 +1576,42 @@ mod tests {
|
|||||||
tree: (justfile (recipe a (body ("foo"))) (recipe b)),
|
tree: (justfile (recipe a (body ("foo"))) (recipe b)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_export_implicit,
|
||||||
|
text: "set export",
|
||||||
|
tree: (justfile (set export true)),
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_export_true,
|
||||||
|
text: "set export := true",
|
||||||
|
tree: (justfile (set export true)),
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_export_false,
|
||||||
|
text: "set export := false",
|
||||||
|
tree: (justfile (set export false)),
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_dotenv_load_implicit,
|
||||||
|
text: "set dotenv-load",
|
||||||
|
tree: (justfile (set dotenv_load true)),
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_dotenv_load_true,
|
||||||
|
text: "set dotenv-load := true",
|
||||||
|
tree: (justfile (set dotenv_load true)),
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_dotenv_load_false,
|
||||||
|
text: "set dotenv-load := false",
|
||||||
|
tree: (justfile (set dotenv_load false)),
|
||||||
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: set_shell_no_arguments,
|
name: set_shell_no_arguments,
|
||||||
text: "set shell := ['tclsh']",
|
text: "set shell := ['tclsh']",
|
||||||
|
@ -3,7 +3,8 @@ use crate::common::*;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum Setting<'src> {
|
pub(crate) enum Setting<'src> {
|
||||||
Shell(Shell<'src>),
|
Shell(Shell<'src>),
|
||||||
Export,
|
Export(bool),
|
||||||
|
DotenvLoad(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
@ -2,15 +2,17 @@ use crate::common::*;
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub(crate) struct Settings<'src> {
|
pub(crate) struct Settings<'src> {
|
||||||
pub(crate) shell: Option<setting::Shell<'src>>,
|
pub(crate) dotenv_load: bool,
|
||||||
pub(crate) export: bool,
|
pub(crate) export: bool,
|
||||||
|
pub(crate) shell: Option<setting::Shell<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Settings<'src> {
|
impl<'src> Settings<'src> {
|
||||||
pub(crate) fn new() -> Settings<'src> {
|
pub(crate) fn new() -> Settings<'src> {
|
||||||
Settings {
|
Settings {
|
||||||
shell: None,
|
dotenv_load: true,
|
||||||
export: false,
|
export: false,
|
||||||
|
shell: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ impl<'src> Token<'src> {
|
|||||||
space_column,
|
space_column,
|
||||||
color.prefix(),
|
color.prefix(),
|
||||||
"",
|
"",
|
||||||
space_width,
|
space_width.max(1),
|
||||||
color.suffix()
|
color.suffix()
|
||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
|
@ -3,8 +3,8 @@ use crate::common::*;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
/// Construct a `Tree` from a symbolic expression literal. This macro, and the
|
/// Construct a `Tree` from a symbolic expression literal. This macro, and the
|
||||||
/// Tree type, are only used in the Parser unit tests, as a concise notation
|
/// Tree type, are only used in the Parser unit tests, providing a concise
|
||||||
/// representing the expected results of parsing a given string.
|
/// notation for representing the expected results of parsing a given string.
|
||||||
macro_rules! tree {
|
macro_rules! tree {
|
||||||
{
|
{
|
||||||
($($child:tt)*)
|
($($child:tt)*)
|
||||||
|
@ -26,3 +26,39 @@ fn dotenv() {
|
|||||||
let stdout = str::from_utf8(&output.stdout).unwrap();
|
let stdout = str::from_utf8(&output.stdout).unwrap();
|
||||||
assert_eq!(stdout, "KEY=SUB\n");
|
assert_eq!(stdout, "KEY=SUB\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_false,
|
||||||
|
justfile: r#"
|
||||||
|
set dotenv-load := false
|
||||||
|
|
||||||
|
foo:
|
||||||
|
if [ -n "${DOTENV_KEY+1}" ]; then echo defined; else echo undefined; fi
|
||||||
|
"#,
|
||||||
|
stdout: "undefined\n",
|
||||||
|
stderr: "if [ -n \"${DOTENV_KEY+1}\" ]; then echo defined; else echo undefined; fi\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_implicit,
|
||||||
|
justfile: r#"
|
||||||
|
set dotenv-load
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo $DOTENV_KEY
|
||||||
|
"#,
|
||||||
|
stdout: "dotenv-value\n",
|
||||||
|
stderr: "echo $DOTENV_KEY\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_true,
|
||||||
|
justfile: r#"
|
||||||
|
set dotenv-load := true
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo $DOTENV_KEY
|
||||||
|
"#,
|
||||||
|
stdout: "dotenv-value\n",
|
||||||
|
stderr: "echo $DOTENV_KEY\n",
|
||||||
|
}
|
||||||
|
@ -81,7 +81,7 @@ recipe:
|
|||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: setting,
|
name: setting_implicit,
|
||||||
justfile: "
|
justfile: "
|
||||||
set export
|
set export
|
||||||
|
|
||||||
@ -97,6 +97,37 @@ test! {
|
|||||||
stderr: "echo $A\necho $B\necho $C\n",
|
stderr: "echo $A\necho $B\necho $C\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: setting_true,
|
||||||
|
justfile: "
|
||||||
|
set export := true
|
||||||
|
|
||||||
|
A := 'hello'
|
||||||
|
|
||||||
|
foo B C=`echo $A`:
|
||||||
|
echo $A
|
||||||
|
echo $B
|
||||||
|
echo $C
|
||||||
|
",
|
||||||
|
args: ("foo", "goodbye"),
|
||||||
|
stdout: "hello\ngoodbye\nhello\n",
|
||||||
|
stderr: "echo $A\necho $B\necho $C\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: setting_false,
|
||||||
|
justfile: r#"
|
||||||
|
set export := false
|
||||||
|
|
||||||
|
A := 'hello'
|
||||||
|
|
||||||
|
foo:
|
||||||
|
if [ -n "${A+1}" ]; then echo defined; else echo undefined; fi
|
||||||
|
"#,
|
||||||
|
stdout: "undefined\n",
|
||||||
|
stderr: "if [ -n \"${A+1}\" ]; then echo defined; else echo undefined; fi\n",
|
||||||
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: setting_shebang,
|
name: setting_shebang,
|
||||||
justfile: "
|
justfile: "
|
||||||
|
@ -65,6 +65,20 @@ test! {
|
|||||||
stderr: "echo bar\n",
|
stderr: "echo bar\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: bad_setting,
|
||||||
|
justfile: "
|
||||||
|
set foo
|
||||||
|
",
|
||||||
|
stderr: "
|
||||||
|
error: Expected ':=', but found end of line
|
||||||
|
|
|
||||||
|
1 | set foo
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
status: EXIT_FAILURE,
|
||||||
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: alias_with_dependencies,
|
name: alias_with_dependencies,
|
||||||
justfile: "foo:\n echo foo\nbar: foo\nalias b := bar",
|
justfile: "foo:\n echo foo\nbar: foo\nalias b := bar",
|
||||||
@ -2214,82 +2228,6 @@ test! {
|
|||||||
",
|
",
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
|
||||||
name: shell_args,
|
|
||||||
justfile: "
|
|
||||||
default:
|
|
||||||
echo A${foo}A
|
|
||||||
",
|
|
||||||
args: ("--shell-arg", "-c"),
|
|
||||||
stdout: "AA\n",
|
|
||||||
stderr: "echo A${foo}A\n",
|
|
||||||
shell: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
test! {
|
|
||||||
name: shell_override,
|
|
||||||
justfile: "
|
|
||||||
set shell := ['foo-bar-baz']
|
|
||||||
|
|
||||||
default:
|
|
||||||
echo hello
|
|
||||||
",
|
|
||||||
args: ("--shell", "bash"),
|
|
||||||
stdout: "hello\n",
|
|
||||||
stderr: "echo hello\n",
|
|
||||||
shell: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
test! {
|
|
||||||
name: shell_arg_override,
|
|
||||||
justfile: "
|
|
||||||
set shell := ['foo-bar-baz']
|
|
||||||
|
|
||||||
default:
|
|
||||||
echo hello
|
|
||||||
",
|
|
||||||
args: ("--shell-arg", "-cu"),
|
|
||||||
stdout: "hello\n",
|
|
||||||
stderr: "echo hello\n",
|
|
||||||
shell: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
test! {
|
|
||||||
name: set_shell,
|
|
||||||
justfile: "
|
|
||||||
set shell := ['echo', '-n']
|
|
||||||
|
|
||||||
x := `bar`
|
|
||||||
|
|
||||||
foo:
|
|
||||||
echo {{x}}
|
|
||||||
echo foo
|
|
||||||
",
|
|
||||||
args: (),
|
|
||||||
stdout: "echo barecho foo",
|
|
||||||
stderr: "echo bar\necho foo\n",
|
|
||||||
shell: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
test! {
|
|
||||||
name: set_shell,
|
|
||||||
justfile: "
|
|
||||||
set shell := ['echo', '-n']
|
|
||||||
|
|
||||||
x := `bar`
|
|
||||||
|
|
||||||
foo:
|
|
||||||
echo {{x}}
|
|
||||||
echo foo
|
|
||||||
",
|
|
||||||
args: (),
|
|
||||||
stdout: "-n echo -n bar\r\r\n-n echo foo\r\n",
|
|
||||||
stderr: "echo -n bar\r\necho foo\n",
|
|
||||||
shell: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: dependency_argument_string,
|
name: dependency_argument_string,
|
||||||
justfile: "
|
justfile: "
|
||||||
|
@ -98,3 +98,79 @@ fn powershell() {
|
|||||||
|
|
||||||
assert_stdout(&output, stdout);
|
assert_stdout(&output, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: shell_args,
|
||||||
|
justfile: "
|
||||||
|
default:
|
||||||
|
echo A${foo}A
|
||||||
|
",
|
||||||
|
args: ("--shell-arg", "-c"),
|
||||||
|
stdout: "AA\n",
|
||||||
|
stderr: "echo A${foo}A\n",
|
||||||
|
shell: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: shell_override,
|
||||||
|
justfile: "
|
||||||
|
set shell := ['foo-bar-baz']
|
||||||
|
|
||||||
|
default:
|
||||||
|
echo hello
|
||||||
|
",
|
||||||
|
args: ("--shell", "bash"),
|
||||||
|
stdout: "hello\n",
|
||||||
|
stderr: "echo hello\n",
|
||||||
|
shell: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: shell_arg_override,
|
||||||
|
justfile: "
|
||||||
|
set shell := ['foo-bar-baz']
|
||||||
|
|
||||||
|
default:
|
||||||
|
echo hello
|
||||||
|
",
|
||||||
|
args: ("--shell-arg", "-cu"),
|
||||||
|
stdout: "hello\n",
|
||||||
|
stderr: "echo hello\n",
|
||||||
|
shell: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
test! {
|
||||||
|
name: set_shell,
|
||||||
|
justfile: "
|
||||||
|
set shell := ['echo', '-n']
|
||||||
|
|
||||||
|
x := `bar`
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo {{x}}
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: (),
|
||||||
|
stdout: "echo barecho foo",
|
||||||
|
stderr: "echo bar\necho foo\n",
|
||||||
|
shell: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
test! {
|
||||||
|
name: set_shell,
|
||||||
|
justfile: "
|
||||||
|
set shell := ['echo', '-n']
|
||||||
|
|
||||||
|
x := `bar`
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo {{x}}
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: (),
|
||||||
|
stdout: "-n echo -n bar\r\r\n-n echo foo\r\n",
|
||||||
|
stderr: "echo -n bar\r\necho foo\n",
|
||||||
|
shell: false,
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user