diff --git a/GRAMMAR.md b/GRAMMAR.md index c72f1c1..c19b24e 100644 --- a/GRAMMAR.md +++ b/GRAMMAR.md @@ -59,14 +59,15 @@ assignment : NAME ':=' expression eol export : 'export' assignment -setting : 'set' 'dotenv-load' boolean? - | 'set' 'ignore-comments' boolean? +setting : 'set' 'allow-duplicate-recipes' boolean? + | 'set' 'dotenv-load' boolean? | 'set' 'export' boolean? | 'set' 'fallback' boolean? + | 'set' 'ignore-comments' boolean? | 'set' 'positional-arguments' boolean? - | 'set' 'allow-duplicate-recipes' boolean? - | 'set' 'windows-powershell' boolean? | 'set' 'shell' ':=' '[' string (',' string)* ','? ']' + | 'set' 'tempdir string + | 'set' 'windows-powershell' boolean? | 'set' 'windows-shell' ':=' '[' string (',' string)* ','? ']' boolean : ':=' ('true' | 'false') diff --git a/README.md b/README.md index 8ff70a2..0af6709 100644 --- a/README.md +++ b/README.md @@ -650,6 +650,7 @@ foo: | `ignore-comments` | boolean | False | Ignore recipe lines beginning with `#`. | | `positional-arguments` | boolean | False | Pass positional arguments. | | `shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. | +| `tempdir` | string | - | Create temporary directories in `tempdir` instead of the system default temporary directory. | | `windows-powershell` | boolean | False | Use PowerShell on Windows as default shell. (Deprecated. Use `windows-shell` instead. | | `windows-shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. | diff --git a/src/analyzer.rs b/src/analyzer.rs index 22fe923..a57c0e5 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -71,6 +71,9 @@ impl<'src> Analyzer<'src> { Setting::WindowsShell(windows_shell) => { settings.windows_shell = Some(windows_shell); } + Setting::Tempdir(tempdir) => { + settings.tempdir = Some(tempdir); + } } } diff --git a/src/keyword.rs b/src/keyword.rs index 11b0f3f..bff1b6c 100644 --- a/src/keyword.rs +++ b/src/keyword.rs @@ -18,6 +18,7 @@ pub(crate) enum Keyword { True, WindowsPowershell, WindowsShell, + Tempdir, } impl Keyword { diff --git a/src/node.rs b/src/node.rs index 8ce634c..b128842 100644 --- a/src/node.rs +++ b/src/node.rs @@ -240,6 +240,9 @@ impl<'src> Node<'src> for Set<'src> { set.push_mut(Tree::string(&argument.cooked)); } } + Setting::Tempdir(value) => { + set.push_mut(Tree::string(value)); + } } set diff --git a/src/parser.rs b/src/parser.rs index 0f8f81e..291ed3d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -796,6 +796,11 @@ impl<'tokens, 'src> Parser<'tokens, 'src> { value: Setting::WindowsShell(self.parse_shell()?), name, }) + } else if name.lexeme() == Keyword::Tempdir.lexeme() { + Ok(Set { + value: Setting::Tempdir(self.parse_string_literal()?.cooked), + name, + }) } else { Err(name.error(CompileErrorKind::UnknownSetting { setting: name.lexeme(), diff --git a/src/recipe.rs b/src/recipe.rs index aa69839..10baf48 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -250,15 +250,17 @@ impl<'src, D> Recipe<'src, D> { message: format!("bad shebang line: {}", shebang_line), })?; - let tmp = tempfile::Builder::new() - .prefix("just") - .tempdir() - .map_err(|error| Error::TmpdirIo { - recipe: self.name(), - io_error: error, - })?; - let mut path = tmp.path().to_path_buf(); - + let mut tempdir_builder = tempfile::Builder::new(); + tempdir_builder.prefix("just"); + let tempdir = match &context.settings.tempdir { + Some(tempdir) => tempdir_builder.tempdir_in(context.search.working_directory.join(tempdir)), + None => tempdir_builder.tempdir(), + } + .map_err(|error| Error::TmpdirIo { + recipe: self.name(), + io_error: error, + })?; + let mut path = tempdir.path().to_path_buf(); path.push(shebang.script_filename(self.name())); { diff --git a/src/setting.rs b/src/setting.rs index 74c23e4..ab17e6f 100644 --- a/src/setting.rs +++ b/src/setting.rs @@ -9,6 +9,7 @@ pub(crate) enum Setting<'src> { IgnoreComments(bool), PositionalArguments(bool), Shell(Shell<'src>), + Tempdir(String), WindowsPowerShell(bool), WindowsShell(Shell<'src>), } @@ -24,6 +25,9 @@ impl<'src> Display for Setting<'src> { | Setting::PositionalArguments(value) | Setting::WindowsPowerShell(value) => write!(f, "{}", value), Setting::Shell(shell) | Setting::WindowsShell(shell) => write!(f, "{}", shell), + Setting::Tempdir(tempdir) => { + write!(f, "{:?}", tempdir) + } } } } diff --git a/src/settings.rs b/src/settings.rs index dbb732c..5c3cc10 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -14,6 +14,7 @@ pub(crate) struct Settings<'src> { pub(crate) ignore_comments: bool, pub(crate) positional_arguments: bool, pub(crate) shell: Option>, + pub(crate) tempdir: Option, pub(crate) windows_powershell: bool, pub(crate) windows_shell: Option>, } diff --git a/tests/json.rs b/tests/json.rs index 399cc1f..1ba0d55 100644 --- a/tests/json.rs +++ b/tests/json.rs @@ -46,6 +46,7 @@ fn alias() { "fallback": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "ignore_comments": false, "windows_powershell": false, "windows_shell": null, @@ -78,6 +79,7 @@ fn assignment() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -123,6 +125,7 @@ fn body() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -179,6 +182,7 @@ fn dependencies() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -272,6 +276,7 @@ fn dependency_argument() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -328,6 +333,7 @@ fn duplicate_recipes() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -366,6 +372,7 @@ fn doc_comment() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -391,6 +398,7 @@ fn empty_justfile() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -531,6 +539,7 @@ fn parameters() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -607,6 +616,7 @@ fn priors() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -645,6 +655,7 @@ fn private() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -683,6 +694,7 @@ fn quiet() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "windows_powershell": false, "windows_shell": null, }, @@ -711,7 +723,6 @@ fn settings() { set positional-arguments set ignore-comments set shell := ['a', 'b', 'c'] - foo: #!bar ", @@ -744,6 +755,7 @@ fn settings() { "arguments": ["b", "c"], "command": "a", }, + "tempdir": null, "windows_powershell": false, "windows_shell": null, }, @@ -785,6 +797,7 @@ fn shebang() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir": null, "windows_powershell": false, "windows_shell": null, }, @@ -823,6 +836,7 @@ fn simple() { "ignore_comments": false, "positional_arguments": false, "shell": null, + "tempdir": null, "windows_powershell": false, "windows_shell": null, }, @@ -863,6 +877,7 @@ fn attribute() { "fallback": false, "positional_arguments": false, "shell": null, + "tempdir" : null, "ignore_comments": false, "windows_powershell": false, "windows_shell": null, diff --git a/tests/tempdir.rs b/tests/tempdir.rs index fb6c82c..843048b 100644 --- a/tests/tempdir.rs +++ b/tests/tempdir.rs @@ -1,6 +1,36 @@ +use super::*; + pub(crate) fn tempdir() -> tempfile::TempDir { tempfile::Builder::new() .prefix("just-test-tempdir") .tempdir() .expect("failed to create temporary directory") } + +#[test] +fn test_tempdir_is_set() { + Test::new() + .justfile( + " + set tempdir := '.' + foo: + #!/usr/bin/env bash + cat just*/foo + ", + ) + .shell(false) + .tree(tree! { + foo: { + } + }) + .current_dir("foo") + .stdout( + " + #!/usr/bin/env bash + + + cat just*/foo + ", + ) + .run(); +}