From 331f61f59cec0f0826381855a5894cc0c94a2010 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Wed, 2 Nov 2022 23:37:35 -0700 Subject: [PATCH] Add [no-cd] attribute (#1400) --- README.md | 36 +++++++++++++++++++++++++------- src/attribute.rs | 1 + src/platform.rs | 16 ++++++++++----- src/platform_interface.rs | 2 +- src/recipe.rs | 28 +++++++++++++++++-------- tests/lib.rs | 1 + tests/no_cd.rs | 43 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 tests/no_cd.rs diff --git a/README.md b/README.md index 7600c83..cfd6772 100644 --- a/README.md +++ b/README.md @@ -1203,13 +1203,14 @@ These functions can fail, for example if a path does not have an extension, whic Recipes may be annotated with attributes that change their behavior. -| Name | Description | -| ------------------- | ------------------------------------------------- | -| `[no-exit-message]` | Don't print an error message when a recipe fails. | -| `[linux]` | Enable recipe on Linux. | -| `[macos]` | Enable recipe on MacOS. | -| `[unix]` | Enable recipe on Unixes. | -| `[windows]` | Enable recipe on Windows. | +| Name | Description | +| ------------------- | ----------------------------------------------- | +| `[no-cd]` | Don't change directory before executing recipe. | +| `[no-exit-message]` | Don't print an error message if recipe fails. | +| `[linux]` | Enable recipe on Linux. | +| `[macos]` | Enable recipe on MacOS. | +| `[unix]` | Enable recipe on Unixes. | +| `[windows]` | Enable recipe on Windows. | #### Enabling and Disabling Recipes @@ -1235,6 +1236,27 @@ run: main.exe ``` +#### Disabling Changing Directorymaster + +`just` normally executes recipes with the current directory set to the +directory that contains the `justfile`. This can be disabled using the +`[no-cd]` attribute. This can be used to create recipes which use paths +relative to the invocation directory, or which operate on the current +directory. + +For exmaple, this `commit` recipe: + +```make +[no-cd] +commit file: + git add {{file}} + git commit +``` + +Can be used with paths that are relative to the current directory, because +`[no-cd]` prevents `just` from changing the current directory when executing +`commit`. + ### Command Evaluation Using Backticks Backticks can be used to store the result of commands: diff --git a/src/attribute.rs b/src/attribute.rs index 375f2bb..c205f34 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -8,6 +8,7 @@ use super::*; pub(crate) enum Attribute { Linux, Macos, + NoCd, NoExitMessage, Unix, Windows, diff --git a/src/platform.rs b/src/platform.rs index 965fac2..9fd9b16 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -6,13 +6,15 @@ pub(crate) struct Platform; impl PlatformInterface for Platform { fn make_shebang_command( path: &Path, - working_directory: &Path, + working_directory: Option<&Path>, _shebang: Shebang, ) -> Result { // shebang scripts can be executed directly on unix let mut cmd = Command::new(path); - cmd.current_dir(working_directory); + if let Some(working_directory) = working_directory { + cmd.current_dir(working_directory); + } Ok(cmd) } @@ -48,7 +50,7 @@ impl PlatformInterface for Platform { impl PlatformInterface for Platform { fn make_shebang_command( path: &Path, - working_directory: &Path, + working_directory: Option<&Path>, shebang: Shebang, ) -> Result { use std::borrow::Cow; @@ -57,7 +59,9 @@ impl PlatformInterface for Platform { let command = if shebang.interpreter.contains('/') { // …translate path to the interpreter from unix style to windows style. let mut cygpath = Command::new("cygpath"); - cygpath.current_dir(working_directory); + if let Some(working_directory) = working_directory { + cygpath.current_dir(working_directory); + } cygpath.arg("--windows"); cygpath.arg(shebang.interpreter); @@ -69,7 +73,9 @@ impl PlatformInterface for Platform { let mut cmd = Command::new(command.as_ref()); - cmd.current_dir(working_directory); + if let Some(working_directory) = working_directory { + cmd.current_dir(working_directory); + } if let Some(argument) = shebang.argument { cmd.arg(argument); diff --git a/src/platform_interface.rs b/src/platform_interface.rs index fcab222..0028e09 100644 --- a/src/platform_interface.rs +++ b/src/platform_interface.rs @@ -5,7 +5,7 @@ pub(crate) trait PlatformInterface { /// shebang line `shebang` fn make_shebang_command( path: &Path, - working_directory: &Path, + working_directory: Option<&Path>, shebang: Shebang, ) -> Result; diff --git a/src/recipe.rs b/src/recipe.rs index 7da2a61..5fda449 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -66,6 +66,10 @@ impl<'src, D> Recipe<'src, D> { !self.private } + pub(crate) fn change_directory(&self) -> bool { + !self.attributes.contains(&Attribute::NoCd) + } + pub(crate) fn enabled(&self) -> bool { let windows = self.attributes.contains(&Attribute::Windows); let linux = self.attributes.contains(&Attribute::Linux); @@ -190,7 +194,9 @@ impl<'src, D> Recipe<'src, D> { let mut cmd = context.settings.shell_command(config); - cmd.current_dir(&context.search.working_directory); + if self.change_directory() { + cmd.current_dir(&context.search.working_directory); + } cmd.arg(command); @@ -322,13 +328,19 @@ impl<'src, D> Recipe<'src, D> { })?; // create a command to run the script - let mut command = - Platform::make_shebang_command(&path, &context.search.working_directory, shebang).map_err( - |output_error| Error::Cygpath { - recipe: self.name(), - output_error, - }, - )?; + let mut command = Platform::make_shebang_command( + &path, + if self.change_directory() { + Some(&context.search.working_directory) + } else { + None + }, + shebang, + ) + .map_err(|output_error| Error::Cygpath { + recipe: self.name(), + output_error, + })?; if context.settings.positional_arguments { command.args(positional); diff --git a/tests/lib.rs b/tests/lib.rs index 7a999fe..e6c7ed4 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -60,6 +60,7 @@ mod json; mod line_prefixes; mod misc; mod multibyte_char; +mod no_cd; mod no_exit_message; mod os_attributes; mod parser; diff --git a/tests/no_cd.rs b/tests/no_cd.rs new file mode 100644 index 0000000..ecdc006 --- /dev/null +++ b/tests/no_cd.rs @@ -0,0 +1,43 @@ +use super::*; + +#[test] +fn linewise() { + Test::new() + .justfile( + " + [no-cd] + foo: + cat bar + ", + ) + .current_dir("foo") + .tree(tree! { + foo: { + bar: "hello", + } + }) + .stderr("cat bar\n") + .stdout("hello") + .run(); +} + +#[test] +fn shebang() { + Test::new() + .justfile( + " + [no-cd] + foo: + #!/bin/sh + cat bar + ", + ) + .current_dir("foo") + .tree(tree! { + foo: { + bar: "hello", + } + }) + .stdout("hello") + .run(); +}