Allow multiple imports of the same file in different modules (#2065)

This commit is contained in:
Casey Rodarmor 2024-05-20 01:04:03 -07:00 committed by GitHub
parent d6b2e6bad2
commit b9f63f1494
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 24 deletions

View File

@ -61,7 +61,7 @@ impl Compiler {
}; };
if let Some(import) = import { if let Some(import) = import {
if srcs.contains_key(&import) { if current.file_path.contains(&import) {
return Err(Error::CircularImport { return Err(Error::CircularImport {
current: current.path, current: current.path,
import, import,
@ -87,7 +87,7 @@ impl Compiler {
.lexiclean(); .lexiclean();
if import.is_file() { if import.is_file() {
if srcs.contains_key(&import) { if current.file_path.contains(&import) {
return Err(Error::CircularImport { return Err(Error::CircularImport {
current: current.path, current: current.path,
import, import,
@ -229,25 +229,10 @@ recipe_b: recipe_c
#[test] #[test]
fn recursive_includes_fail() { 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! { let tmp = temptree! {
justfile: justfile_a, justfile: "import './subdir/b'\na: b",
subdir: { subdir: {
justfile_b: justfile_b b: "import '../justfile'\nb:"
} }
}; };
@ -257,7 +242,7 @@ recipe_b:
let loader_output = Compiler::compile(false, &loader, &justfile_a_path).unwrap_err(); let loader_output = Compiler::compile(false, &loader, &justfile_a_path).unwrap_err();
assert_matches!(loader_output, Error::CircularImport { current, import } assert_matches!(loader_output, Error::CircularImport { current, import }
if current == tmp.path().join("subdir").join("justfile_b").lexiclean() && if current == tmp.path().join("subdir").join("b").lexiclean() &&
import == tmp.path().join("justfile").lexiclean() import == tmp.path().join("justfile").lexiclean()
); );
} }

View File

@ -3,6 +3,7 @@ use super::*;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Source<'src> { pub(crate) struct Source<'src> {
pub(crate) file_depth: u32, pub(crate) file_depth: u32,
pub(crate) file_path: Vec<PathBuf>,
pub(crate) namepath: Namepath<'src>, pub(crate) namepath: Namepath<'src>,
pub(crate) path: PathBuf, pub(crate) path: PathBuf,
pub(crate) submodule_depth: u32, pub(crate) submodule_depth: u32,
@ -13,6 +14,7 @@ impl<'src> Source<'src> {
pub(crate) fn root(path: &Path) -> Self { pub(crate) fn root(path: &Path) -> Self {
Self { Self {
file_depth: 0, file_depth: 0,
file_path: vec![path.into()],
namepath: Namepath::default(), namepath: Namepath::default(),
path: path.into(), path: path.into(),
submodule_depth: 0, submodule_depth: 0,
@ -23,6 +25,12 @@ impl<'src> Source<'src> {
pub(crate) fn import(&self, path: PathBuf) -> Self { pub(crate) fn import(&self, path: PathBuf) -> Self {
Self { Self {
file_depth: self.file_depth + 1, file_depth: self.file_depth + 1,
file_path: self
.file_path
.clone()
.into_iter()
.chain(iter::once(path.clone()))
.collect(),
namepath: self.namepath.clone(), namepath: self.namepath.clone(),
path, path,
submodule_depth: self.submodule_depth, submodule_depth: self.submodule_depth,
@ -33,10 +41,16 @@ impl<'src> Source<'src> {
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, 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), namepath: self.namepath.join(name),
path: path.clone(),
submodule_depth: self.submodule_depth + 1, submodule_depth: self.submodule_depth + 1,
working_directory: path.parent().unwrap().into(), working_directory: path.parent().unwrap().into(),
path,
} }
} }
} }

View File

@ -361,3 +361,22 @@ fn recipes_imported_in_root_run_in_command_line_provided_working_directory() {
.stdout("BAZBAZ") .stdout("BAZBAZ")
.run(); .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();
}