Run imported recipes in root justfile with correct working directory (#2056)
This commit is contained in:
parent
b1c7491486
commit
104608d8cc
@ -133,7 +133,7 @@ impl<'src> Analyzer<'src> {
|
|||||||
define(recipe.name, "recipe", settings.allow_duplicate_recipes)?;
|
define(recipe.name, "recipe", settings.allow_duplicate_recipes)?;
|
||||||
if recipe_table
|
if recipe_table
|
||||||
.get(recipe.name.lexeme())
|
.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());
|
recipe_table.insert(recipe.clone());
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,10 @@ impl Compiler {
|
|||||||
loaded.push(relative.into());
|
loaded.push(relative.into());
|
||||||
let tokens = Lexer::lex(relative, src)?;
|
let tokens = Lexer::lex(relative, src)?;
|
||||||
let mut ast = Parser::parse(
|
let mut ast = Parser::parse(
|
||||||
|
current.file_depth,
|
||||||
¤t.path,
|
¤t.path,
|
||||||
¤t.namepath,
|
¤t.namepath,
|
||||||
current.depth,
|
current.submodule_depth,
|
||||||
&tokens,
|
&tokens,
|
||||||
¤t.working_directory,
|
¤t.working_directory,
|
||||||
)?;
|
)?;
|
||||||
@ -169,6 +170,7 @@ impl Compiler {
|
|||||||
pub(crate) fn test_compile(src: &str) -> CompileResult<Justfile> {
|
pub(crate) fn test_compile(src: &str) -> CompileResult<Justfile> {
|
||||||
let tokens = Lexer::test_lex(src)?;
|
let tokens = Lexer::test_lex(src)?;
|
||||||
let ast = Parser::parse(
|
let ast = Parser::parse(
|
||||||
|
0,
|
||||||
&PathBuf::new(),
|
&PathBuf::new(),
|
||||||
&Namepath::default(),
|
&Namepath::default(),
|
||||||
0,
|
0,
|
||||||
|
@ -25,6 +25,7 @@ use {super::*, TokenKind::*};
|
|||||||
/// contents of the set is printed in the resultant error message.
|
/// contents of the set is printed in the resultant error message.
|
||||||
pub(crate) struct Parser<'run, 'src> {
|
pub(crate) struct Parser<'run, 'src> {
|
||||||
expected_tokens: BTreeSet<TokenKind>,
|
expected_tokens: BTreeSet<TokenKind>,
|
||||||
|
file_depth: u32,
|
||||||
file_path: &'run Path,
|
file_path: &'run Path,
|
||||||
module_namepath: &'run Namepath<'src>,
|
module_namepath: &'run Namepath<'src>,
|
||||||
next_token: usize,
|
next_token: usize,
|
||||||
@ -37,6 +38,7 @@ pub(crate) struct Parser<'run, 'src> {
|
|||||||
impl<'run, 'src> Parser<'run, 'src> {
|
impl<'run, 'src> Parser<'run, 'src> {
|
||||||
/// Parse `tokens` into an `Ast`
|
/// Parse `tokens` into an `Ast`
|
||||||
pub(crate) fn parse(
|
pub(crate) fn parse(
|
||||||
|
file_depth: u32,
|
||||||
file_path: &'run Path,
|
file_path: &'run Path,
|
||||||
module_namepath: &'run Namepath<'src>,
|
module_namepath: &'run Namepath<'src>,
|
||||||
submodule_depth: u32,
|
submodule_depth: u32,
|
||||||
@ -45,6 +47,7 @@ impl<'run, 'src> Parser<'run, 'src> {
|
|||||||
) -> CompileResult<'src, Ast<'src>> {
|
) -> CompileResult<'src, Ast<'src>> {
|
||||||
Self {
|
Self {
|
||||||
expected_tokens: BTreeSet::new(),
|
expected_tokens: BTreeSet::new(),
|
||||||
|
file_depth,
|
||||||
file_path,
|
file_path,
|
||||||
module_namepath,
|
module_namepath,
|
||||||
next_token: 0,
|
next_token: 0,
|
||||||
@ -456,7 +459,7 @@ impl<'run, 'src> Parser<'run, 'src> {
|
|||||||
let value = self.parse_expression()?;
|
let value = self.parse_expression()?;
|
||||||
self.expect_eol()?;
|
self.expect_eol()?;
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
depth: self.submodule_depth,
|
depth: self.file_depth,
|
||||||
export,
|
export,
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
@ -769,8 +772,8 @@ impl<'run, 'src> Parser<'run, 'src> {
|
|||||||
attributes,
|
attributes,
|
||||||
body,
|
body,
|
||||||
dependencies,
|
dependencies,
|
||||||
depth: self.submodule_depth,
|
|
||||||
doc,
|
doc,
|
||||||
|
file_depth: self.file_depth,
|
||||||
file_path: self.file_path.into(),
|
file_path: self.file_path.into(),
|
||||||
name,
|
name,
|
||||||
namepath: self.module_namepath.join(name),
|
namepath: self.module_namepath.join(name),
|
||||||
@ -778,6 +781,7 @@ impl<'run, 'src> Parser<'run, 'src> {
|
|||||||
priors,
|
priors,
|
||||||
private: name.lexeme().starts_with('_'),
|
private: name.lexeme().starts_with('_'),
|
||||||
quiet,
|
quiet,
|
||||||
|
submodule_depth: self.submodule_depth,
|
||||||
working_directory: self.working_directory.into(),
|
working_directory: self.working_directory.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1010,6 +1014,7 @@ mod tests {
|
|||||||
let unindented = unindent(text);
|
let unindented = unindent(text);
|
||||||
let tokens = Lexer::test_lex(&unindented).expect("lexing failed");
|
let tokens = Lexer::test_lex(&unindented).expect("lexing failed");
|
||||||
let justfile = Parser::parse(
|
let justfile = Parser::parse(
|
||||||
|
0,
|
||||||
&PathBuf::new(),
|
&PathBuf::new(),
|
||||||
&Namepath::default(),
|
&Namepath::default(),
|
||||||
0,
|
0,
|
||||||
@ -1055,6 +1060,7 @@ mod tests {
|
|||||||
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
|
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
|
||||||
|
|
||||||
match Parser::parse(
|
match Parser::parse(
|
||||||
|
0,
|
||||||
&PathBuf::new(),
|
&PathBuf::new(),
|
||||||
&Namepath::default(),
|
&Namepath::default(),
|
||||||
0,
|
0,
|
||||||
|
@ -22,10 +22,10 @@ pub(crate) struct Recipe<'src, D = Dependency<'src>> {
|
|||||||
pub(crate) attributes: BTreeSet<Attribute<'src>>,
|
pub(crate) attributes: BTreeSet<Attribute<'src>>,
|
||||||
pub(crate) body: Vec<Line<'src>>,
|
pub(crate) body: Vec<Line<'src>>,
|
||||||
pub(crate) dependencies: Vec<D>,
|
pub(crate) dependencies: Vec<D>,
|
||||||
#[serde(skip)]
|
|
||||||
pub(crate) depth: u32,
|
|
||||||
pub(crate) doc: Option<&'src str>,
|
pub(crate) doc: Option<&'src str>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
pub(crate) file_depth: u32,
|
||||||
|
#[serde(skip)]
|
||||||
pub(crate) file_path: PathBuf,
|
pub(crate) file_path: PathBuf,
|
||||||
pub(crate) name: Name<'src>,
|
pub(crate) name: Name<'src>,
|
||||||
pub(crate) namepath: Namepath<'src>,
|
pub(crate) namepath: Namepath<'src>,
|
||||||
@ -35,6 +35,8 @@ pub(crate) struct Recipe<'src, D = Dependency<'src>> {
|
|||||||
pub(crate) quiet: bool,
|
pub(crate) quiet: bool,
|
||||||
pub(crate) shebang: bool,
|
pub(crate) shebang: bool,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
pub(crate) submodule_depth: u32,
|
||||||
|
#[serde(skip)]
|
||||||
pub(crate) working_directory: PathBuf,
|
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> {
|
fn working_directory<'a>(&'a self, search: &'a Search) -> Option<&Path> {
|
||||||
if self.change_directory() {
|
if self.change_directory() {
|
||||||
Some(if self.depth > 0 {
|
Some(if self.submodule_depth > 0 {
|
||||||
&self.working_directory
|
&self.working_directory
|
||||||
} else {
|
} else {
|
||||||
&search.working_directory
|
&search.working_directory
|
||||||
|
@ -1,37 +1,41 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub(crate) struct Source<'src> {
|
pub(crate) struct Source<'src> {
|
||||||
pub(crate) path: PathBuf,
|
pub(crate) file_depth: u32,
|
||||||
pub(crate) depth: u32,
|
|
||||||
pub(crate) namepath: Namepath<'src>,
|
pub(crate) namepath: Namepath<'src>,
|
||||||
|
pub(crate) path: PathBuf,
|
||||||
|
pub(crate) submodule_depth: u32,
|
||||||
pub(crate) working_directory: PathBuf,
|
pub(crate) working_directory: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Source<'src> {
|
impl<'src> Source<'src> {
|
||||||
pub(crate) fn root(path: &Path) -> Self {
|
pub(crate) fn root(path: &Path) -> Self {
|
||||||
Self {
|
Self {
|
||||||
path: path.into(),
|
file_depth: 0,
|
||||||
depth: 0,
|
|
||||||
namepath: Namepath::default(),
|
namepath: Namepath::default(),
|
||||||
|
path: path.into(),
|
||||||
|
submodule_depth: 0,
|
||||||
working_directory: path.parent().unwrap().into(),
|
working_directory: path.parent().unwrap().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn import(&self, path: PathBuf) -> Self {
|
pub(crate) fn import(&self, path: PathBuf) -> Self {
|
||||||
Self {
|
Self {
|
||||||
depth: self.depth + 1,
|
file_depth: self.file_depth + 1,
|
||||||
path,
|
|
||||||
namepath: self.namepath.clone(),
|
namepath: self.namepath.clone(),
|
||||||
|
path,
|
||||||
|
submodule_depth: self.submodule_depth,
|
||||||
working_directory: self.working_directory.clone(),
|
working_directory: self.working_directory.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn module(&self, name: Name<'src>, path: PathBuf) -> Self {
|
pub(crate) fn module(&self, name: Name<'src>, path: PathBuf) -> Self {
|
||||||
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(),
|
working_directory: path.parent().unwrap().into(),
|
||||||
path,
|
path,
|
||||||
depth: self.depth + 1,
|
|
||||||
namepath: self.namepath.join(name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ pub(crate) fn analysis_error(
|
|||||||
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
|
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
|
||||||
|
|
||||||
let ast = Parser::parse(
|
let ast = Parser::parse(
|
||||||
|
0,
|
||||||
&PathBuf::new(),
|
&PathBuf::new(),
|
||||||
&Namepath::default(),
|
&Namepath::default(),
|
||||||
0,
|
0,
|
||||||
|
@ -48,8 +48,8 @@ impl<'src> UnresolvedRecipe<'src> {
|
|||||||
attributes: self.attributes,
|
attributes: self.attributes,
|
||||||
body: self.body,
|
body: self.body,
|
||||||
dependencies,
|
dependencies,
|
||||||
depth: self.depth,
|
|
||||||
doc: self.doc,
|
doc: self.doc,
|
||||||
|
file_depth: self.file_depth,
|
||||||
file_path: self.file_path,
|
file_path: self.file_path,
|
||||||
name: self.name,
|
name: self.name,
|
||||||
namepath: self.namepath,
|
namepath: self.namepath,
|
||||||
@ -58,6 +58,7 @@ impl<'src> UnresolvedRecipe<'src> {
|
|||||||
private: self.private,
|
private: self.private,
|
||||||
quiet: self.quiet,
|
quiet: self.quiet,
|
||||||
shebang: self.shebang,
|
shebang: self.shebang,
|
||||||
|
submodule_depth: self.submodule_depth,
|
||||||
working_directory: self.working_directory,
|
working_directory: self.working_directory,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -344,3 +344,20 @@ fn shebang_recipes_in_imports_in_root_run_in_justfile_directory() {
|
|||||||
.stdout("BAZ")
|
.stdout("BAZ")
|
||||||
.run();
|
.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();
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user