Run imported recipes in root justfile with correct working directory (#2056)

This commit is contained in:
Casey Rodarmor 2024-05-18 23:38:57 -07:00 committed by GitHub
parent b1c7491486
commit 104608d8cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 49 additions and 16 deletions

View File

@ -133,7 +133,7 @@ impl<'src> Analyzer<'src> {
define(recipe.name, "recipe", settings.allow_duplicate_recipes)?;
if recipe_table
.get(recipe.name.lexeme())
.map_or(true, |original| recipe.depth <= original.depth)
.map_or(true, |original| recipe.file_depth <= original.file_depth)
{
recipe_table.insert(recipe.clone());
}

View File

@ -21,9 +21,10 @@ impl Compiler {
loaded.push(relative.into());
let tokens = Lexer::lex(relative, src)?;
let mut ast = Parser::parse(
current.file_depth,
&current.path,
&current.namepath,
current.depth,
current.submodule_depth,
&tokens,
&current.working_directory,
)?;
@ -169,6 +170,7 @@ impl Compiler {
pub(crate) fn test_compile(src: &str) -> CompileResult<Justfile> {
let tokens = Lexer::test_lex(src)?;
let ast = Parser::parse(
0,
&PathBuf::new(),
&Namepath::default(),
0,

View File

@ -25,6 +25,7 @@ use {super::*, TokenKind::*};
/// contents of the set is printed in the resultant error message.
pub(crate) struct Parser<'run, 'src> {
expected_tokens: BTreeSet<TokenKind>,
file_depth: u32,
file_path: &'run Path,
module_namepath: &'run Namepath<'src>,
next_token: usize,
@ -37,6 +38,7 @@ pub(crate) struct Parser<'run, 'src> {
impl<'run, 'src> Parser<'run, 'src> {
/// Parse `tokens` into an `Ast`
pub(crate) fn parse(
file_depth: u32,
file_path: &'run Path,
module_namepath: &'run Namepath<'src>,
submodule_depth: u32,
@ -45,6 +47,7 @@ impl<'run, 'src> Parser<'run, 'src> {
) -> CompileResult<'src, Ast<'src>> {
Self {
expected_tokens: BTreeSet::new(),
file_depth,
file_path,
module_namepath,
next_token: 0,
@ -456,7 +459,7 @@ impl<'run, 'src> Parser<'run, 'src> {
let value = self.parse_expression()?;
self.expect_eol()?;
Ok(Assignment {
depth: self.submodule_depth,
depth: self.file_depth,
export,
name,
value,
@ -769,8 +772,8 @@ impl<'run, 'src> Parser<'run, 'src> {
attributes,
body,
dependencies,
depth: self.submodule_depth,
doc,
file_depth: self.file_depth,
file_path: self.file_path.into(),
name,
namepath: self.module_namepath.join(name),
@ -778,6 +781,7 @@ impl<'run, 'src> Parser<'run, 'src> {
priors,
private: name.lexeme().starts_with('_'),
quiet,
submodule_depth: self.submodule_depth,
working_directory: self.working_directory.into(),
})
}
@ -1010,6 +1014,7 @@ mod tests {
let unindented = unindent(text);
let tokens = Lexer::test_lex(&unindented).expect("lexing failed");
let justfile = Parser::parse(
0,
&PathBuf::new(),
&Namepath::default(),
0,
@ -1055,6 +1060,7 @@ mod tests {
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
match Parser::parse(
0,
&PathBuf::new(),
&Namepath::default(),
0,

View File

@ -22,10 +22,10 @@ pub(crate) struct Recipe<'src, D = Dependency<'src>> {
pub(crate) attributes: BTreeSet<Attribute<'src>>,
pub(crate) body: Vec<Line<'src>>,
pub(crate) dependencies: Vec<D>,
#[serde(skip)]
pub(crate) depth: u32,
pub(crate) doc: Option<&'src str>,
#[serde(skip)]
pub(crate) file_depth: u32,
#[serde(skip)]
pub(crate) file_path: PathBuf,
pub(crate) name: Name<'src>,
pub(crate) namepath: Namepath<'src>,
@ -35,6 +35,8 @@ pub(crate) struct Recipe<'src, D = Dependency<'src>> {
pub(crate) quiet: bool,
pub(crate) shebang: bool,
#[serde(skip)]
pub(crate) submodule_depth: u32,
#[serde(skip)]
pub(crate) working_directory: PathBuf,
}
@ -126,7 +128,7 @@ impl<'src, D> Recipe<'src, D> {
fn working_directory<'a>(&'a self, search: &'a Search) -> Option<&Path> {
if self.change_directory() {
Some(if self.depth > 0 {
Some(if self.submodule_depth > 0 {
&self.working_directory
} else {
&search.working_directory

View File

@ -1,37 +1,41 @@
use super::*;
pub(crate) struct Source<'src> {
pub(crate) path: PathBuf,
pub(crate) depth: u32,
pub(crate) file_depth: u32,
pub(crate) namepath: Namepath<'src>,
pub(crate) path: PathBuf,
pub(crate) submodule_depth: u32,
pub(crate) working_directory: PathBuf,
}
impl<'src> Source<'src> {
pub(crate) fn root(path: &Path) -> Self {
Self {
path: path.into(),
depth: 0,
file_depth: 0,
namepath: Namepath::default(),
path: path.into(),
submodule_depth: 0,
working_directory: path.parent().unwrap().into(),
}
}
pub(crate) fn import(&self, path: PathBuf) -> Self {
Self {
depth: self.depth + 1,
path,
file_depth: self.file_depth + 1,
namepath: self.namepath.clone(),
path,
submodule_depth: self.submodule_depth,
working_directory: self.working_directory.clone(),
}
}
pub(crate) fn module(&self, name: Name<'src>, path: PathBuf) -> Self {
Self {
file_depth: self.file_depth + 1,
namepath: self.namepath.join(name),
submodule_depth: self.submodule_depth + 1,
working_directory: path.parent().unwrap().into(),
path,
depth: self.depth + 1,
namepath: self.namepath.join(name),
}
}
}

View File

@ -60,6 +60,7 @@ pub(crate) fn analysis_error(
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
let ast = Parser::parse(
0,
&PathBuf::new(),
&Namepath::default(),
0,

View File

@ -48,8 +48,8 @@ impl<'src> UnresolvedRecipe<'src> {
attributes: self.attributes,
body: self.body,
dependencies,
depth: self.depth,
doc: self.doc,
file_depth: self.file_depth,
file_path: self.file_path,
name: self.name,
namepath: self.namepath,
@ -58,6 +58,7 @@ impl<'src> UnresolvedRecipe<'src> {
private: self.private,
quiet: self.quiet,
shebang: self.shebang,
submodule_depth: self.submodule_depth,
working_directory: self.working_directory,
})
}

View File

@ -344,3 +344,20 @@ fn shebang_recipes_in_imports_in_root_run_in_justfile_directory() {
.stdout("BAZ")
.run();
}
#[test]
fn recipes_imported_in_root_run_in_command_line_provided_working_directory() {
Test::new()
.write("subdir/b.justfile", "@b:\n cat baz")
.write("subdir/a.justfile", "import 'b.justfile'\n@a: b\n cat baz")
.write("baz", "BAZ")
.args([
"--working-directory",
".",
"--justfile",
"subdir/a.justfile",
])
.test_round_trip(false)
.stdout("BAZBAZ")
.run();
}