Don't default to included recipes (#1740)
This commit is contained in:
parent
7337447d42
commit
ab16c0493f
@ -9,14 +9,16 @@ pub(crate) struct Analyzer<'src> {
|
|||||||
|
|
||||||
impl<'src> Analyzer<'src> {
|
impl<'src> Analyzer<'src> {
|
||||||
pub(crate) fn analyze(
|
pub(crate) fn analyze(
|
||||||
|
paths: &HashMap<PathBuf, PathBuf>,
|
||||||
asts: &HashMap<PathBuf, Ast<'src>>,
|
asts: &HashMap<PathBuf, Ast<'src>>,
|
||||||
root: &Path,
|
root: &Path,
|
||||||
) -> CompileResult<'src, Justfile<'src>> {
|
) -> CompileResult<'src, Justfile<'src>> {
|
||||||
Analyzer::default().justfile(asts, root)
|
Analyzer::default().justfile(paths, asts, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn justfile(
|
fn justfile(
|
||||||
mut self,
|
mut self,
|
||||||
|
paths: &HashMap<PathBuf, PathBuf>,
|
||||||
asts: &HashMap<PathBuf, Ast<'src>>,
|
asts: &HashMap<PathBuf, Ast<'src>>,
|
||||||
root: &Path,
|
root: &Path,
|
||||||
) -> CompileResult<'src, Justfile<'src>> {
|
) -> CompileResult<'src, Justfile<'src>> {
|
||||||
@ -83,9 +85,12 @@ impl<'src> Analyzer<'src> {
|
|||||||
aliases.insert(Self::resolve_alias(&recipes, alias)?);
|
aliases.insert(Self::resolve_alias(&recipes, alias)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let root = paths.get(root).unwrap();
|
||||||
|
|
||||||
Ok(Justfile {
|
Ok(Justfile {
|
||||||
first: recipes
|
first: recipes
|
||||||
.values()
|
.values()
|
||||||
|
.filter(|recipe| recipe.name.path == root)
|
||||||
.fold(None, |accumulator, next| match accumulator {
|
.fold(None, |accumulator, next| match accumulator {
|
||||||
None => Some(Rc::clone(next)),
|
None => Some(Rc::clone(next)),
|
||||||
Some(previous) => Some(if previous.line_number() < next.line_number() {
|
Some(previous) => Some(if previous.line_number() < next.line_number() {
|
||||||
|
@ -10,12 +10,15 @@ impl Compiler {
|
|||||||
) -> RunResult<'src, Compilation<'src>> {
|
) -> RunResult<'src, Compilation<'src>> {
|
||||||
let mut srcs: HashMap<PathBuf, &str> = HashMap::new();
|
let mut srcs: HashMap<PathBuf, &str> = HashMap::new();
|
||||||
let mut asts: HashMap<PathBuf, Ast> = 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();
|
let mut stack: Vec<PathBuf> = Vec::new();
|
||||||
paths.push(root.into());
|
stack.push(root.into());
|
||||||
|
|
||||||
while let Some(current) = paths.pop() {
|
while let Some(current) = stack.pop() {
|
||||||
let (relative, src) = loader.load(root, ¤t)?;
|
let (relative, src) = loader.load(root, ¤t)?;
|
||||||
|
paths.insert(current.clone(), relative.into());
|
||||||
|
|
||||||
let tokens = Lexer::lex(relative, src)?;
|
let tokens = Lexer::lex(relative, src)?;
|
||||||
let mut ast = Parser::parse(&tokens)?;
|
let mut ast = Parser::parse(&tokens)?;
|
||||||
|
|
||||||
@ -37,14 +40,14 @@ impl Compiler {
|
|||||||
|
|
||||||
*absolute = Some(include.clone());
|
*absolute = Some(include.clone());
|
||||||
|
|
||||||
paths.push(include);
|
stack.push(include);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asts.insert(current.clone(), ast.clone());
|
asts.insert(current.clone(), ast.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let justfile = Analyzer::analyze(&asts, root)?;
|
let justfile = Analyzer::analyze(&paths, &asts, root)?;
|
||||||
|
|
||||||
Ok(Compilation {
|
Ok(Compilation {
|
||||||
asts,
|
asts,
|
||||||
@ -61,7 +64,9 @@ impl Compiler {
|
|||||||
let root = PathBuf::from("justfile");
|
let root = PathBuf::from("justfile");
|
||||||
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
|
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
|
||||||
asts.insert(root.clone(), ast);
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ pub(crate) enum Error<'src> {
|
|||||||
io_error: io::Error,
|
io_error: io::Error,
|
||||||
},
|
},
|
||||||
NoChoosableRecipes,
|
NoChoosableRecipes,
|
||||||
|
NoDefaultRecipe,
|
||||||
NoRecipes,
|
NoRecipes,
|
||||||
NotConfirmed {
|
NotConfirmed {
|
||||||
recipe: &'src str,
|
recipe: &'src str,
|
||||||
@ -350,6 +351,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
|||||||
write!(f, "Failed to read justfile at `{path}`: {io_error}")?;
|
write!(f, "Failed to read justfile at `{path}`: {io_error}")?;
|
||||||
}
|
}
|
||||||
NoChoosableRecipes => write!(f, "Justfile contains no choosable recipes.")?,
|
NoChoosableRecipes => write!(f, "Justfile contains no choosable recipes.")?,
|
||||||
|
NoDefaultRecipe => write!(f, "Justfile contains no default recipe.")?,
|
||||||
NoRecipes => write!(f, "Justfile contains no recipes.")?,
|
NoRecipes => write!(f, "Justfile contains no recipes.")?,
|
||||||
NotConfirmed { recipe } => {
|
NotConfirmed { recipe } => {
|
||||||
write!(f, "Recipe `{recipe}` was not confirmed")?;
|
write!(f, "Recipe `{recipe}` was not confirmed")?;
|
||||||
|
@ -199,8 +199,10 @@ impl<'src> Justfile<'src> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
vec![recipe.name()]
|
vec![recipe.name()]
|
||||||
} else {
|
} else if self.recipes.is_empty() {
|
||||||
return Err(Error::NoRecipes);
|
return Err(Error::NoRecipes);
|
||||||
|
} else {
|
||||||
|
return Err(Error::NoDefaultRecipe);
|
||||||
};
|
};
|
||||||
|
|
||||||
let arguments = argvec.as_slice();
|
let arguments = argvec.as_slice();
|
||||||
|
@ -25,6 +25,10 @@ impl<'key, V: Keyed<'key>> Table<'key, V> {
|
|||||||
self.map.get(key)
|
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> {
|
pub(crate) fn values(&self) -> btree_map::Values<&'key str, V> {
|
||||||
self.map.values()
|
self.map.values()
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,10 @@ pub(crate) fn analysis_error(
|
|||||||
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
|
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
|
||||||
asts.insert(root.clone(), ast);
|
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"),
|
Ok(_) => panic!("Analysis unexpectedly succeeded"),
|
||||||
Err(have) => {
|
Err(have) => {
|
||||||
let want = CompileError {
|
let want = CompileError {
|
||||||
|
@ -37,12 +37,15 @@ fn include_succeeds_with_unstable() {
|
|||||||
fn trailing_spaces_after_include_are_ignored() {
|
fn trailing_spaces_after_include_are_ignored() {
|
||||||
Test::new()
|
Test::new()
|
||||||
.tree(tree! {
|
.tree(tree! {
|
||||||
"include.justfile": "
|
"include.justfile": "",
|
||||||
a:
|
|
||||||
@echo A
|
|
||||||
",
|
|
||||||
})
|
})
|
||||||
.justfile("!include ./include.justfile\x20")
|
.justfile(
|
||||||
|
"
|
||||||
|
!include ./include.justfile\x20
|
||||||
|
a:
|
||||||
|
@echo A
|
||||||
|
",
|
||||||
|
)
|
||||||
.arg("--unstable")
|
.arg("--unstable")
|
||||||
.test_round_trip(false)
|
.test_round_trip(false)
|
||||||
.stdout("A\n")
|
.stdout("A\n")
|
||||||
@ -103,3 +106,17 @@ fn circular_include() {
|
|||||||
))
|
))
|
||||||
.run();
|
.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();
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user