summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasey Rodarmor <casey@rodarmor.com>2023-11-22 10:27:49 -0800
committerGitHub <noreply@github.com>2023-11-22 18:27:49 +0000
commitab16c0493fab440bde485f874223dde950085c80 (patch)
treefe971cb3a2d97e91bd50a036c49c488e98f18536
parent7337447d429d15c5e10da443f270c5766f2e8c6d (diff)
Don't default to included recipes (#1740)
-rw-r--r--src/analyzer.rs7
-rw-r--r--src/compiler.rs17
-rw-r--r--src/error.rs2
-rw-r--r--src/justfile.rs4
-rw-r--r--src/table.rs4
-rw-r--r--src/testing.rs5
-rw-r--r--tests/includes.rs27
7 files changed, 52 insertions, 14 deletions
diff --git a/src/analyzer.rs b/src/analyzer.rs
index ff4051c3..24710f8d 100644
--- a/src/analyzer.rs
+++ b/src/analyzer.rs
@@ -9,14 +9,16 @@ pub(crate) struct Analyzer<'src> {
impl<'src> Analyzer<'src> {
pub(crate) fn analyze(
+ paths: &HashMap<PathBuf, PathBuf>,
asts: &HashMap<PathBuf, Ast<'src>>,
root: &Path,
) -> CompileResult<'src, Justfile<'src>> {
- Analyzer::default().justfile(asts, root)
+ Analyzer::default().justfile(paths, asts, root)
}
fn justfile(
mut self,
+ paths: &HashMap<PathBuf, PathBuf>,
asts: &HashMap<PathBuf, Ast<'src>>,
root: &Path,
) -> CompileResult<'src, Justfile<'src>> {
@@ -83,9 +85,12 @@ impl<'src> Analyzer<'src> {
aliases.insert(Self::resolve_alias(&recipes, alias)?);
}
+ let root = paths.get(root).unwrap();
+
Ok(Justfile {
first: recipes
.values()
+ .filter(|recipe| recipe.name.path == root)
.fold(None, |accumulator, next| match accumulator {
None => Some(Rc::clone(next)),
Some(previous) => Some(if previous.line_number() < next.line_number() {
diff --git a/src/compiler.rs b/src/compiler.rs
index 95ecc571..e7fb7ccb 100644
--- a/src/compiler.rs
+++ b/src/compiler.rs
@@ -10,12 +10,15 @@ impl Compiler {
) -> RunResult<'src, Compilation<'src>> {
let mut srcs: HashMap<PathBuf, &str> = HashMap::new();
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
+ let mut paths: HashMap<PathBuf, PathBuf> = HashMap::new();
- let mut paths: Vec<PathBuf> = Vec::new();
- paths.push(root.into());
+ let mut stack: Vec<PathBuf> = Vec::new();
+ stack.push(root.into());
- while let Some(current) = paths.pop() {
+ while let Some(current) = stack.pop() {
let (relative, src) = loader.load(root, &current)?;
+ paths.insert(current.clone(), relative.into());
+
let tokens = Lexer::lex(relative, src)?;
let mut ast = Parser::parse(&tokens)?;
@@ -37,14 +40,14 @@ impl Compiler {
*absolute = Some(include.clone());
- paths.push(include);
+ stack.push(include);
}
}
asts.insert(current.clone(), ast.clone());
}
- let justfile = Analyzer::analyze(&asts, root)?;
+ let justfile = Analyzer::analyze(&paths, &asts, root)?;
Ok(Compilation {
asts,
@@ -61,7 +64,9 @@ impl Compiler {
let root = PathBuf::from("justfile");
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
asts.insert(root.clone(), ast);
- Analyzer::analyze(&asts, &root)
+ let mut paths: HashMap<PathBuf, PathBuf> = HashMap::new();
+ paths.insert(root.clone(), root.clone());
+ Analyzer::analyze(&paths, &asts, &root)
}
}
diff --git a/src/error.rs b/src/error.rs
index d7573cf4..2259b056 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -106,6 +106,7 @@ pub(crate) enum Error<'src> {
io_error: io::Error,
},
NoChoosableRecipes,
+ NoDefaultRecipe,
NoRecipes,
NotConfirmed {
recipe: &'src str,
@@ -350,6 +351,7 @@ impl<'src> ColorDisplay for Error<'src> {
write!(f, "Failed to read justfile at `{path}`: {io_error}")?;
}
NoChoosableRecipes => write!(f, "Justfile contains no choosable recipes.")?,
+ NoDefaultRecipe => write!(f, "Justfile contains no default recipe.")?,
NoRecipes => write!(f, "Justfile contains no recipes.")?,
NotConfirmed { recipe } => {
write!(f, "Recipe `{recipe}` was not confirmed")?;
diff --git a/src/justfile.rs b/src/justfile.rs
index 3648c769..a4bbcc93 100644
--- a/src/justfile.rs
+++ b/src/justfile.rs
@@ -199,8 +199,10 @@ impl<'src> Justfile<'src> {
});
}
vec![recipe.name()]
- } else {
+ } else if self.recipes.is_empty() {
return Err(Error::NoRecipes);
+ } else {
+ return Err(Error::NoDefaultRecipe);
};
let arguments = argvec.as_slice();
diff --git a/src/table.rs b/src/table.rs
index 0c60602d..db5ff526 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -25,6 +25,10 @@ impl<'key, V: Keyed<'key>> Table<'key, V> {
self.map.get(key)
}
+ pub(crate) fn is_empty(&self) -> bool {
+ self.map.is_empty()
+ }
+
pub(crate) fn values(&self) -> btree_map::Values<&'key str, V> {
self.map.values()
}
diff --git a/src/testing.rs b/src/testing.rs
index 91549a82..b0f6c4bf 100644
--- a/src/testing.rs
+++ b/src/testing.rs
@@ -65,7 +65,10 @@ pub(crate) fn analysis_error(
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
asts.insert(root.clone(), ast);
- match Analyzer::analyze(&asts, &root) {
+ let mut paths: HashMap<PathBuf, PathBuf> = HashMap::new();
+ paths.insert("justfile".into(), "justfile".into());
+
+ match Analyzer::analyze(&paths, &asts, &root) {
Ok(_) => panic!("Analysis unexpectedly succeeded"),
Err(have) => {
let want = CompileError {
diff --git a/tests/includes.rs b/tests/includes.rs
index 2460a451..af2e7b66 100644
--- a/tests/includes.rs
+++ b/tests/includes.rs
@@ -37,12 +37,15 @@ fn include_succeeds_with_unstable() {
fn trailing_spaces_after_include_are_ignored() {
Test::new()
.tree(tree! {
- "include.justfile": "
- a:
- @echo A
- ",
+ "include.justfile": "",
})
- .justfile("!include ./include.justfile\x20")
+ .justfile(
+ "
+ !include ./include.justfile\x20
+ a:
+ @echo A
+ ",
+ )
.arg("--unstable")
.test_round_trip(false)
.stdout("A\n")
@@ -103,3 +106,17 @@ fn circular_include() {
))
.run();
}
+
+#[test]
+fn include_recipes_are_not_default() {
+ Test::new()
+ .tree(tree! {
+ "include.justfile": "bar:",
+ })
+ .justfile("!include ./include.justfile")
+ .arg("--unstable")
+ .test_round_trip(false)
+ .status(EXIT_FAILURE)
+ .stderr("error: Justfile contains no default recipe.\n")
+ .run();
+}