Add --allow-missing to ignore missing recipe and submodule errors (#2460)

This commit is contained in:
Razvan Maracine 2024-11-23 22:22:01 +02:00 committed by GitHub
parent ce9062abde
commit 40840a042f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 91 additions and 21 deletions

View file

@ -9,6 +9,7 @@ use {
#[derive(Debug, PartialEq)]
pub(crate) struct Config {
pub(crate) allow_missing: bool,
pub(crate) check: bool,
pub(crate) color: Color,
pub(crate) command_color: Option<ansi_term::Color>,
@ -80,6 +81,7 @@ mod cmd {
}
mod arg {
pub(crate) const ALLOW_MISSING: &str = "ALLOW-MISSING";
pub(crate) const ARGUMENTS: &str = "ARGUMENTS";
pub(crate) const CHECK: &str = "CHECK";
pub(crate) const CHOOSER: &str = "CHOOSER";
@ -315,6 +317,13 @@ impl Config {
.help("Suppress all output")
.conflicts_with(arg::DRY_RUN),
)
.arg(
Arg::new(arg::ALLOW_MISSING)
.long("allow-missing")
.env("JUST_ALLOW_MISSING")
.action(ArgAction::SetTrue)
.help("Ignore missing recipe and module errors"),
)
.arg(
Arg::new(arg::SET)
.long("set")
@ -706,6 +715,7 @@ impl Config {
let explain = matches.get_flag(arg::EXPLAIN);
Ok(Self {
allow_missing: matches.get_flag(arg::ALLOW_MISSING),
check: matches.get_flag(arg::CHECK),
color: (*matches.get_one::<UseColor>(arg::COLOR).unwrap()).into(),
command_color: matches

View file

@ -468,7 +468,7 @@ impl<'src> ColorDisplay for Error<'src> {
write!(f, "{count} {overrides} overridden on the command line but not present in justfile")?;
}
UnknownRecipe { recipe, suggestion } => {
write!(f, "Justfile does not contain recipe `{recipe}`.")?;
write!(f, "Justfile does not contain recipe `{recipe}`")?;
if let Some(suggestion) = suggestion {
write!(f, "\n{suggestion}")?;
}

View file

@ -145,6 +145,15 @@ impl Subcommand {
}
}
if config.allow_missing
&& matches!(
result,
Err(Error::UnknownRecipe { .. } | Error::UnknownSubmodule { .. })
)
{
return Ok(());
}
return result;
}
}

50
tests/allow_missing.rs Normal file
View file

@ -0,0 +1,50 @@
use super::*;
#[test]
fn allow_missing_recipes_in_run_invocation() {
Test::new()
.arg("foo")
.stderr("error: Justfile does not contain recipe `foo`\n")
.status(EXIT_FAILURE)
.run();
Test::new().args(["--allow-missing", "foo"]).run();
}
#[test]
fn allow_missing_modules_in_run_invocation() {
Test::new()
.arg("foo::bar")
.stderr("error: Justfile does not contain submodule `foo`\n")
.status(EXIT_FAILURE)
.run();
Test::new().args(["--allow-missing", "foo::bar"]).run();
}
#[test]
fn allow_missing_does_not_apply_to_compilation_errors() {
Test::new()
.justfile("bar: foo")
.args(["--allow-missing", "foo"])
.stderr(
"
error: Recipe `bar` has unknown dependency `foo`
justfile:1:6
1 bar: foo
^^^
",
)
.status(EXIT_FAILURE)
.run();
}
#[test]
fn allow_missing_does_not_apply_to_other_subcommands() {
Test::new()
.args(["--allow-missing", "--show", "foo"])
.stderr("error: Justfile does not contain recipe `foo`\n")
.status(EXIT_FAILURE)
.run();
}

View file

@ -176,7 +176,7 @@ fn requires_setting() {
.args(["foo"])
.current_dir("bar")
.status(EXIT_FAILURE)
.stderr("error: Justfile does not contain recipe `foo`.\n")
.stderr("error: Justfile does not contain recipe `foo`\n")
.run();
}
@ -230,7 +230,7 @@ fn doesnt_work_with_justfile() {
.args(["--justfile", "justfile", "foo"])
.current_dir("bar")
.status(EXIT_FAILURE)
.stderr("error: Justfile does not contain recipe `foo`.\n")
.stderr("error: Justfile does not contain recipe `foo`\n")
.run();
}
@ -254,7 +254,7 @@ fn doesnt_work_with_justfile_and_working_directory() {
.args(["--justfile", "justfile", "--working-directory", ".", "foo"])
.current_dir("bar")
.status(EXIT_FAILURE)
.stderr("error: Justfile does not contain recipe `foo`.\n")
.stderr("error: Justfile does not contain recipe `foo`\n")
.run();
}
@ -282,7 +282,7 @@ fn prints_correct_error_message_when_recipe_not_found() {
.status(EXIT_FAILURE)
.stderr(
"
error: Justfile does not contain recipe `foo`.
error: Justfile does not contain recipe `foo`
",
)
.run();
@ -355,7 +355,7 @@ fn stop_fallback_when_fallback_is_false() {
.current_dir("a/b")
.stderr(
"
error: Justfile does not contain recipe `baz`.
error: Justfile does not contain recipe `baz`
Did you mean `bar`?
",
)

View file

@ -33,6 +33,7 @@ mod test;
mod allow_duplicate_recipes;
mod allow_duplicate_variables;
mod allow_missing;
mod assert_stdout;
mod assert_success;
mod assertions;

View file

@ -594,7 +594,7 @@ foo A B:
",
args: ("foo", "ONE", "TWO", "THREE"),
stdout: "",
stderr: "error: Justfile does not contain recipe `THREE`.\n",
stderr: "error: Justfile does not contain recipe `THREE`\n",
status: EXIT_FAILURE,
}
@ -618,7 +618,7 @@ foo A B='B':
",
args: ("foo", "ONE", "TWO", "THREE"),
stdout: "",
stderr: "error: Justfile does not contain recipe `THREE`.\n",
stderr: "error: Justfile does not contain recipe `THREE`\n",
status: EXIT_FAILURE,
}
@ -643,7 +643,7 @@ test! {
justfile: "hello:",
args: ("foo"),
stdout: "",
stderr: "error: Justfile does not contain recipe `foo`.\n",
stderr: "error: Justfile does not contain recipe `foo`\n",
status: EXIT_FAILURE,
}
@ -652,7 +652,7 @@ test! {
justfile: "hello:",
args: ("foo", "bar"),
stdout: "",
stderr: "error: Justfile does not contain recipe `foo`.\n",
stderr: "error: Justfile does not contain recipe `foo`\n",
status: EXIT_FAILURE,
}
@ -999,7 +999,7 @@ a Z="\t z":
"#,
args: ("hell"),
stdout: "",
stderr: "error: Justfile does not contain recipe `hell`.\nDid you mean `hello`?\n",
stderr: "error: Justfile does not contain recipe `hell`\nDid you mean `hello`?\n",
status: EXIT_FAILURE,
}

View file

@ -77,19 +77,19 @@ fn nested_module_recipes_can_be_run_with_path_syntax() {
fn invalid_path_syntax() {
Test::new()
.arg(":foo::foo")
.stderr("error: Justfile does not contain recipe `:foo::foo`.\n")
.stderr("error: Justfile does not contain recipe `:foo::foo`\n")
.status(EXIT_FAILURE)
.run();
Test::new()
.arg("foo::foo:")
.stderr("error: Justfile does not contain recipe `foo::foo:`.\n")
.stderr("error: Justfile does not contain recipe `foo::foo:`\n")
.status(EXIT_FAILURE)
.run();
Test::new()
.arg("foo:::foo")
.stderr("error: Justfile does not contain recipe `foo:::foo`.\n")
.stderr("error: Justfile does not contain recipe `foo:::foo`\n")
.status(EXIT_FAILURE)
.run();
}
@ -99,7 +99,7 @@ fn missing_recipe_after_invalid_path() {
Test::new()
.arg(":foo::foo")
.arg("bar")
.stderr("error: Justfile does not contain recipe `:foo::foo`.\n")
.stderr("error: Justfile does not contain recipe `:foo::foo`\n")
.status(EXIT_FAILURE)
.run();
}
@ -655,7 +655,7 @@ fn submodule_recipe_not_found_spaced_error_message() {
",
)
.args(["foo", "baz"])
.stderr("error: Justfile does not contain recipe `foo baz`.\nDid you mean `bar`?\n")
.stderr("error: Justfile does not contain recipe `foo baz`\nDid you mean `bar`?\n")
.status(1)
.run();
}
@ -670,7 +670,7 @@ fn submodule_recipe_not_found_colon_separated_error_message() {
",
)
.args(["foo::baz"])
.stderr("error: Justfile does not contain recipe `foo::baz`.\nDid you mean `bar`?\n")
.stderr("error: Justfile does not contain recipe `foo::baz`\nDid you mean `bar`?\n")
.status(1)
.run();
}

View file

@ -48,7 +48,7 @@ a Z="\t z":
"#,
args: ("--show", "hell"),
stdout: "",
stderr: "error: Justfile does not contain recipe `hell`.\nDid you mean `hello`?\n",
stderr: "error: Justfile does not contain recipe `hell`\nDid you mean `hello`?\n",
status: EXIT_FAILURE,
}
@ -65,7 +65,7 @@ a Z="\t z":
args: ("--show", "fo"),
stdout: "",
stderr: "
error: Justfile does not contain recipe `fo`.
error: Justfile does not contain recipe `fo`
Did you mean `foo`, an alias for `hello`?
",
status: EXIT_FAILURE,
@ -81,7 +81,7 @@ a Z="\t z":
"#,
args: ("--show", "hell"),
stdout: "",
stderr: "error: Justfile does not contain recipe `hell`.\n",
stderr: "error: Justfile does not contain recipe `hell`\n",
status: EXIT_FAILURE,
}
@ -97,7 +97,7 @@ a Z="\t z":
"#,
args: ("--show", "fooooooo"),
stdout: "",
stderr: "error: Justfile does not contain recipe `fooooooo`.\n",
stderr: "error: Justfile does not contain recipe `fooooooo`\n",
status: EXIT_FAILURE,
}