1
1
mirror of https://github.com/casey/just.git synced 2024-11-29 14:15:32 +03:00

Add --one flag to forbid multiple recipes from being invoked on the command line (#2374)

This commit is contained in:
Casey Rodarmor 2024-09-21 13:25:52 +08:00 committed by GitHub
parent 19018d1ba3
commit 4d865a1645
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 97 additions and 8 deletions

View File

@ -753,6 +753,48 @@ $ just --list --list-heading ''
build build
``` ```
### Invoking Multiple Recipes
Multiple recipes may be invoked on the command line at once:
```just
build:
make web
serve:
python3 -m http.server -d out 8000
```
```sh
$ just build serve
make web
python3 -m http.server -d out 8000
```
Keep in mind that recipes with parameters will swallow arguments, even if they
match the names of other recipes:
```just
build project:
make {{project}}
serve:
python3 -m http.server -d out 8000
```
```sh
$ just build serve
make: *** No rule to make target `serve'. Stop.
```
The `--one` flag can be used to restrict command-line invocations to a single
recipe:
```sh
$ just --one build serve
error: Expected 1 command-line recipe invocation but found 2.
```
### Working Directory ### Working Directory
By default, recipes run with the working directory set to the directory that By default, recipes run with the working directory set to the directory that

View File

@ -25,6 +25,7 @@ pub(crate) struct Config {
pub(crate) load_dotenv: bool, pub(crate) load_dotenv: bool,
pub(crate) no_aliases: bool, pub(crate) no_aliases: bool,
pub(crate) no_dependencies: bool, pub(crate) no_dependencies: bool,
pub(crate) one: bool,
pub(crate) search_config: SearchConfig, pub(crate) search_config: SearchConfig,
pub(crate) shell: Option<String>, pub(crate) shell: Option<String>,
pub(crate) shell_args: Option<Vec<String>>, pub(crate) shell_args: Option<Vec<String>>,
@ -100,6 +101,7 @@ mod arg {
pub(crate) const NO_DEPS: &str = "NO-DEPS"; pub(crate) const NO_DEPS: &str = "NO-DEPS";
pub(crate) const NO_DOTENV: &str = "NO-DOTENV"; pub(crate) const NO_DOTENV: &str = "NO-DOTENV";
pub(crate) const NO_HIGHLIGHT: &str = "NO-HIGHLIGHT"; pub(crate) const NO_HIGHLIGHT: &str = "NO-HIGHLIGHT";
pub(crate) const ONE: &str = "ONE";
pub(crate) const QUIET: &str = "QUIET"; pub(crate) const QUIET: &str = "QUIET";
pub(crate) const SET: &str = "SET"; pub(crate) const SET: &str = "SET";
pub(crate) const SHELL: &str = "SHELL"; pub(crate) const SHELL: &str = "SHELL";
@ -297,6 +299,13 @@ impl Config {
.help("Don't highlight echoed recipe lines in bold") .help("Don't highlight echoed recipe lines in bold")
.overrides_with(arg::HIGHLIGHT), .overrides_with(arg::HIGHLIGHT),
) )
.arg(
Arg::new(arg::ONE)
.long("one")
.env("JUST_ONE")
.action(ArgAction::SetTrue)
.help("Forbid multiple recipes from being invoked on the command line"),
)
.arg( .arg(
Arg::new(arg::QUIET) Arg::new(arg::QUIET)
.short('q') .short('q')
@ -721,6 +730,7 @@ impl Config {
load_dotenv: !matches.get_flag(arg::NO_DOTENV), load_dotenv: !matches.get_flag(arg::NO_DOTENV),
no_aliases: matches.get_flag(arg::NO_ALIASES), no_aliases: matches.get_flag(arg::NO_ALIASES),
no_dependencies: matches.get_flag(arg::NO_DEPS), no_dependencies: matches.get_flag(arg::NO_DEPS),
one: matches.get_flag(arg::ONE),
search_config, search_config,
shell: matches.get_one::<String>(arg::SHELL).map(Into::into), shell: matches.get_one::<String>(arg::SHELL).map(Into::into),
shell_args: if matches.get_flag(arg::CLEAR_SHELL_ARGS) { shell_args: if matches.get_flag(arg::CLEAR_SHELL_ARGS) {

View File

@ -95,6 +95,9 @@ pub(crate) enum Error<'src> {
variable: String, variable: String,
suggestion: Option<Suggestion<'src>>, suggestion: Option<Suggestion<'src>>,
}, },
ExcessInvocations {
invocations: usize,
},
ExpectedSubmoduleButFoundRecipe { ExpectedSubmoduleButFoundRecipe {
path: String, path: String,
}, },
@ -373,6 +376,9 @@ impl<'src> ColorDisplay for Error<'src> {
write!(f, "\n{suggestion}")?; write!(f, "\n{suggestion}")?;
} }
} }
ExcessInvocations { invocations } => {
write!(f, "Expected 1 command-line recipe invocation but found {invocations}.")?;
},
ExpectedSubmoduleButFoundRecipe { path } => { ExpectedSubmoduleButFoundRecipe { path } => {
write!(f, "Expected submodule at `{path}` but found recipe.")?; write!(f, "Expected submodule at `{path}` but found recipe.")?;
}, },

View File

@ -202,6 +202,12 @@ impl<'src> Justfile<'src> {
)?); )?);
} }
if config.one && invocations.len() > 1 {
return Err(Error::ExcessInvocations {
invocations: invocations.len(),
});
}
let mut ran = Ran::default(); let mut ran = Ran::default();
for invocation in invocations { for invocation in invocations {
let context = ExecutionContext { let context = ExecutionContext {

View File

@ -5,15 +5,40 @@ fn dont_run_duplicate_recipes() {
Test::new() Test::new()
.justfile( .justfile(
" "
foo: @foo:
# foo echo foo
", ",
) )
.args(["foo", "foo"]) .args(["foo", "foo"])
.stderr( .stdout("foo\n")
" .run();
# foo }
",
) #[test]
fn one_flag_only_allows_one_invocation() {
Test::new()
.justfile(
"
@foo:
echo foo
",
)
.args(["--one", "foo"])
.stdout("foo\n")
.run();
Test::new()
.justfile(
"
@foo:
echo foo
@bar:
echo bar
",
)
.args(["--one", "foo", "bar"])
.stderr("error: Expected 1 command-line recipe invocation but found 2.\n")
.status(1)
.run(); .run();
} }