From 76bc9706866574c9a9c17b551c26a85b073ec983 Mon Sep 17 00:00:00 2001 From: James Hilliard Date: Tue, 23 Jul 2024 11:01:06 -0600 Subject: [PATCH] Don't check .gitignore files outside of projet directory When building inside a .gitignore'd output directory as part of another build system maturin may accidentially pick up the parent .gitignore. Lets just disable searching for parent .gitignore files since this functionality is broken anyways as the logic does not match git's .gitignore logic anyways. For example in buildroot we have an output directory that has its contents gitignored in which maturin will build packages, changing some minor implementation details in how we ignore this directory triggered this bug. https://github.com/buildroot/buildroot/commit/a14c862c08865e053d5fce90a0d0323b8f9e4bc0 As the output dir files are supposed to be ignored both before and after this change this indicates that ignore::WalkBuilder parent matching is fundamentally broken and can not be used reliably in the first place as it does not match git's ignore logic. Also disable git exclude and git global excludes which may cause problems. Signed-off-by: James Hilliard --- src/build_context.rs | 5 ++ src/module_writer.rs | 55 ++++++++++++------- src/source_distribution.rs | 2 +- test-crates/pyo3-mixed-implicit/.gitignore | 1 + .../pyo3-mixed-include-exclude/.gitignore | 1 + test-crates/pyo3-mixed-py-subdir/.gitignore | 1 + test-crates/pyo3-mixed-src/.gitignore | 1 + test-crates/pyo3-mixed/.gitignore | 1 + tests/run.rs | 2 + 9 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 test-crates/pyo3-mixed-implicit/.gitignore create mode 100644 test-crates/pyo3-mixed-include-exclude/.gitignore create mode 100644 test-crates/pyo3-mixed-py-subdir/.gitignore create mode 100644 test-crates/pyo3-mixed-src/.gitignore create mode 100644 test-crates/pyo3-mixed/.gitignore diff --git a/src/build_context.rs b/src/build_context.rs index 91faf4f0..7353e936 100644 --- a/src/build_context.rs +++ b/src/build_context.rs @@ -680,6 +680,7 @@ impl BuildContext { &self.target, self.editable, self.pyproject_toml.as_ref(), + &self.pyproject_toml_path, ) .context("Failed to add the files to the wheel")?; @@ -758,6 +759,7 @@ impl BuildContext { &self.target, self.editable, self.pyproject_toml.as_ref(), + &self.pyproject_toml_path, ) .context("Failed to add the files to the wheel")?; @@ -881,6 +883,7 @@ impl BuildContext { &self.interpreter[0].executable, self.editable, self.pyproject_toml.as_ref(), + &self.pyproject_toml_path, )?; self.add_pth(&mut writer)?; @@ -947,6 +950,7 @@ impl BuildContext { self.target.target_os(), self.editable, self.pyproject_toml.as_ref(), + &self.pyproject_toml_path, )?; self.add_pth(&mut writer)?; @@ -1040,6 +1044,7 @@ impl BuildContext { &mut writer, &self.project_layout, self.pyproject_toml.as_ref(), + self.pyproject_toml_path.as_ref(), ) .context("Failed to add the python module to the package")?; } diff --git a/src/module_writer.rs b/src/module_writer.rs index 309d0890..e1658696 100644 --- a/src/module_writer.rs +++ b/src/module_writer.rs @@ -803,6 +803,7 @@ pub fn write_bindings_module( target: &Target, editable: bool, pyproject_toml: Option<&PyProjectToml>, + pyproject_toml_path: &Path, ) -> Result<()> { let ext_name = &project_layout.extension_name; let so_filename = if is_abi3 { @@ -824,7 +825,7 @@ pub fn write_bindings_module( }; if !editable { - write_python_part(writer, project_layout, pyproject_toml) + write_python_part(writer, project_layout, pyproject_toml, pyproject_toml_path) .context("Failed to add the python module to the package")?; } if let Some(python_module) = &project_layout.python_module { @@ -853,7 +854,7 @@ pub fn write_bindings_module( writer.add_directory(&module)?; // Reexport the shared library as if it were the top level module writer.add_bytes( - &module.join("__init__.py"), + module.join("__init__.py"), None, format!( r#"from .{ext_name} import * @@ -867,10 +868,10 @@ if hasattr({ext_name}, "__all__"): let type_stub = project_layout.rust_module.join(format!("{ext_name}.pyi")); if type_stub.exists() { eprintln!("📖 Found type stub file at {ext_name}.pyi"); - writer.add_file(&module.join("__init__.pyi"), type_stub)?; - writer.add_bytes(&module.join("py.typed"), None, b"")?; + writer.add_file(module.join("__init__.pyi"), type_stub)?; + writer.add_bytes(module.join("py.typed"), None, b"")?; } - writer.add_file_with_permissions(&module.join(so_filename), artifact, 0o755)?; + writer.add_file_with_permissions(module.join(so_filename), artifact, 0o755)?; } Ok(()) @@ -888,11 +889,12 @@ pub fn write_cffi_module( python: &Path, editable: bool, pyproject_toml: Option<&PyProjectToml>, + pyproject_toml_path: &Path, ) -> Result<()> { let cffi_declarations = generate_cffi_declarations(crate_dir, target_dir, python)?; if !editable { - write_python_part(writer, project_layout, pyproject_toml) + write_python_part(writer, project_layout, pyproject_toml, pyproject_toml_path) .context("Failed to add the python module to the package")?; } @@ -931,20 +933,20 @@ pub fn write_cffi_module( .join(format!("{module_name}.pyi")); if type_stub.exists() { eprintln!("📖 Found type stub file at {module_name}.pyi"); - writer.add_file(&module.join("__init__.pyi"), type_stub)?; - writer.add_bytes(&module.join("py.typed"), None, b"")?; + writer.add_file(module.join("__init__.pyi"), type_stub)?; + writer.add_bytes(module.join("py.typed"), None, b"")?; } }; if !editable || project_layout.python_module.is_none() { writer.add_bytes( - &module.join("__init__.py"), + module.join("__init__.py"), None, cffi_init_file(&project_layout.extension_name).as_bytes(), )?; - writer.add_bytes(&module.join("ffi.py"), None, cffi_declarations.as_bytes())?; + writer.add_bytes(module.join("ffi.py"), None, cffi_declarations.as_bytes())?; writer.add_file_with_permissions( - &module.join(format!( + module.join(format!( "{extension_name}.so", extension_name = &project_layout.extension_name )), @@ -1124,6 +1126,7 @@ pub fn write_uniffi_module( target_os: Os, editable: bool, pyproject_toml: Option<&PyProjectToml>, + pyproject_toml_path: &Path, ) -> Result<()> { let UniFfiBindings { name: binding_name, @@ -1133,7 +1136,7 @@ pub fn write_uniffi_module( let py_init = format!("from .{binding_name} import * # NOQA\n"); if !editable { - write_python_part(writer, project_layout, pyproject_toml) + write_python_part(writer, project_layout, pyproject_toml, pyproject_toml_path) .context("Failed to add the python module to the package")?; } @@ -1174,18 +1177,18 @@ pub fn write_uniffi_module( .join(format!("{module_name}.pyi")); if type_stub.exists() { eprintln!("📖 Found type stub file at {module_name}.pyi"); - writer.add_file(&module.join("__init__.pyi"), type_stub)?; - writer.add_bytes(&module.join("py.typed"), None, b"")?; + writer.add_file(module.join("__init__.pyi"), type_stub)?; + writer.add_bytes(module.join("py.typed"), None, b"")?; } }; if !editable || project_layout.python_module.is_none() { - writer.add_bytes(&module.join("__init__.py"), None, py_init.as_bytes())?; + writer.add_bytes(module.join("__init__.py"), None, py_init.as_bytes())?; writer.add_file( module.join(binding_name).with_extension("py"), uniffi_binding, )?; - writer.add_file_with_permissions(&module.join(cdylib), artifact, 0o755)?; + writer.add_file_with_permissions(module.join(cdylib), artifact, 0o755)?; } Ok(()) @@ -1208,7 +1211,7 @@ pub fn write_bin( writer.add_directory(&data_dir)?; // We can't use add_file since we need to mark the file as executable - writer.add_file_with_permissions(&data_dir.join(bin_name), artifact, 0o755)?; + writer.add_file_with_permissions(data_dir.join(bin_name), artifact, 0o755)?; Ok(()) } @@ -1271,6 +1274,7 @@ pub fn write_python_part( writer: &mut impl ModuleWriter, project_layout: &ProjectLayout, pyproject_toml: Option<&PyProjectToml>, + pyproject_toml_path: &Path, ) -> Result<()> { let python_dir = &project_layout.python_dir; let mut python_packages = Vec::new(); @@ -1286,8 +1290,17 @@ pub fn write_python_part( } for package in python_packages { - for absolute in WalkBuilder::new(package).hidden(false).build() { + for absolute in WalkBuilder::new(pyproject_toml_path.parent().unwrap()) + .hidden(false) + .parents(false) + .git_global(false) + .git_exclude(false) + .build() + { let absolute = absolute?.into_path(); + if !absolute.starts_with(package.as_path()) { + continue; + } let relative = absolute.strip_prefix(python_dir).unwrap(); if absolute.is_dir() { writer.add_directory(relative)?; @@ -1353,13 +1366,13 @@ pub fn write_dist_info( writer.add_directory(&dist_info_dir)?; writer.add_bytes( - &dist_info_dir.join("METADATA"), + dist_info_dir.join("METADATA"), None, metadata23.to_file_contents()?.as_bytes(), )?; writer.add_bytes( - &dist_info_dir.join("WHEEL"), + dist_info_dir.join("WHEEL"), None, wheel_file(tags)?.as_bytes(), )?; @@ -1376,7 +1389,7 @@ pub fn write_dist_info( } if !entry_points.is_empty() { writer.add_bytes( - &dist_info_dir.join("entry_points.txt"), + dist_info_dir.join("entry_points.txt"), None, entry_points.as_bytes(), )?; diff --git a/src/source_distribution.rs b/src/source_distribution.rs index 8502e00c..6f8e8ded 100644 --- a/src/source_distribution.rs +++ b/src/source_distribution.rs @@ -412,7 +412,7 @@ fn add_cargo_package_files_to_sdist( add_crate_to_source_distribution( writer, &path_dep.manifest_path, - &root_dir.join(relative_path_dep_manifest_dir), + root_dir.join(relative_path_dep_manifest_dir), &known_path_deps, false, skip_cargo_toml, diff --git a/test-crates/pyo3-mixed-implicit/.gitignore b/test-crates/pyo3-mixed-implicit/.gitignore new file mode 100644 index 00000000..18880a5a --- /dev/null +++ b/test-crates/pyo3-mixed-implicit/.gitignore @@ -0,0 +1 @@ +*.py[cdo] diff --git a/test-crates/pyo3-mixed-include-exclude/.gitignore b/test-crates/pyo3-mixed-include-exclude/.gitignore new file mode 100644 index 00000000..18880a5a --- /dev/null +++ b/test-crates/pyo3-mixed-include-exclude/.gitignore @@ -0,0 +1 @@ +*.py[cdo] diff --git a/test-crates/pyo3-mixed-py-subdir/.gitignore b/test-crates/pyo3-mixed-py-subdir/.gitignore new file mode 100644 index 00000000..18880a5a --- /dev/null +++ b/test-crates/pyo3-mixed-py-subdir/.gitignore @@ -0,0 +1 @@ +*.py[cdo] diff --git a/test-crates/pyo3-mixed-src/.gitignore b/test-crates/pyo3-mixed-src/.gitignore new file mode 100644 index 00000000..18880a5a --- /dev/null +++ b/test-crates/pyo3-mixed-src/.gitignore @@ -0,0 +1 @@ +*.py[cdo] diff --git a/test-crates/pyo3-mixed/.gitignore b/test-crates/pyo3-mixed/.gitignore new file mode 100644 index 00000000..18880a5a --- /dev/null +++ b/test-crates/pyo3-mixed/.gitignore @@ -0,0 +1 @@ +*.py[cdo] diff --git a/tests/run.rs b/tests/run.rs index d5383563..7455faab 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -730,6 +730,7 @@ fn pyo3_mixed_include_exclude_sdist() { SdistGenerator::Cargo, expect![[r#" { + "pyo3_mixed_include_exclude-2.1.3/.gitignore", "pyo3_mixed_include_exclude-2.1.3/Cargo.lock", "pyo3_mixed_include_exclude-2.1.3/Cargo.toml", "pyo3_mixed_include_exclude-2.1.3/PKG-INFO", @@ -759,6 +760,7 @@ fn pyo3_mixed_include_exclude_git_sdist_generator() { SdistGenerator::Git, expect![[r#" { + "pyo3_mixed_include_exclude-2.1.3/.gitignore", "pyo3_mixed_include_exclude-2.1.3/Cargo.lock", "pyo3_mixed_include_exclude-2.1.3/Cargo.toml", "pyo3_mixed_include_exclude-2.1.3/PKG-INFO",