From b9f63f1494654536d4ea319c26ccf37d9f19e451 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Mon, 20 May 2024 01:04:03 -0700 Subject: [PATCH] Allow multiple imports of the same file in different modules (#2065) --- src/compiler.rs | 31 ++++++++----------------------- src/source.rs | 16 +++++++++++++++- tests/imports.rs | 19 +++++++++++++++++++ 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index a1e987a1..ac3dfc75 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -61,7 +61,7 @@ impl Compiler { }; if let Some(import) = import { - if srcs.contains_key(&import) { + if current.file_path.contains(&import) { return Err(Error::CircularImport { current: current.path, import, @@ -87,7 +87,7 @@ impl Compiler { .lexiclean(); if import.is_file() { - if srcs.contains_key(&import) { + if current.file_path.contains(&import) { return Err(Error::CircularImport { current: current.path, import, @@ -229,26 +229,11 @@ recipe_b: recipe_c #[test] fn recursive_includes_fail() { - let justfile_a = r#" -# A comment at the top of the file -import "./subdir/justfile_b" - -some_recipe: recipe_b - echo "some recipe" - -"#; - - let justfile_b = r#" -import "../justfile" - -recipe_b: - echo "recipe b" -"#; let tmp = temptree! { - justfile: justfile_a, - subdir: { - justfile_b: justfile_b - } + justfile: "import './subdir/b'\na: b", + subdir: { + b: "import '../justfile'\nb:" + } }; let loader = Loader::new(); @@ -257,8 +242,8 @@ recipe_b: let loader_output = Compiler::compile(false, &loader, &justfile_a_path).unwrap_err(); assert_matches!(loader_output, Error::CircularImport { current, import } - if current == tmp.path().join("subdir").join("justfile_b").lexiclean() && - import == tmp.path().join("justfile").lexiclean() + if current == tmp.path().join("subdir").join("b").lexiclean() && + import == tmp.path().join("justfile").lexiclean() ); } } diff --git a/src/source.rs b/src/source.rs index 1da7a5f7..00754215 100644 --- a/src/source.rs +++ b/src/source.rs @@ -3,6 +3,7 @@ use super::*; #[derive(Debug)] pub(crate) struct Source<'src> { pub(crate) file_depth: u32, + pub(crate) file_path: Vec, pub(crate) namepath: Namepath<'src>, pub(crate) path: PathBuf, pub(crate) submodule_depth: u32, @@ -13,6 +14,7 @@ impl<'src> Source<'src> { pub(crate) fn root(path: &Path) -> Self { Self { file_depth: 0, + file_path: vec![path.into()], namepath: Namepath::default(), path: path.into(), submodule_depth: 0, @@ -23,6 +25,12 @@ impl<'src> Source<'src> { pub(crate) fn import(&self, path: PathBuf) -> Self { Self { file_depth: self.file_depth + 1, + file_path: self + .file_path + .clone() + .into_iter() + .chain(iter::once(path.clone())) + .collect(), namepath: self.namepath.clone(), path, submodule_depth: self.submodule_depth, @@ -33,10 +41,16 @@ impl<'src> Source<'src> { pub(crate) fn module(&self, name: Name<'src>, path: PathBuf) -> Self { Self { file_depth: self.file_depth + 1, + file_path: self + .file_path + .clone() + .into_iter() + .chain(iter::once(path.clone())) + .collect(), namepath: self.namepath.join(name), + path: path.clone(), submodule_depth: self.submodule_depth + 1, working_directory: path.parent().unwrap().into(), - path, } } } diff --git a/tests/imports.rs b/tests/imports.rs index ce6dcf94..448af29d 100644 --- a/tests/imports.rs +++ b/tests/imports.rs @@ -361,3 +361,22 @@ fn recipes_imported_in_root_run_in_command_line_provided_working_directory() { .stdout("BAZBAZ") .run(); } + +#[test] +fn reused_import_are_allowed() { + Test::new() + .justfile( + " + import 'a' + import 'b' + + bar: + ", + ) + .tree(tree! { + a: "import 'c'", + b: "import 'c'", + c: "", + }) + .run(); +}