diff --git a/src/module_writer/wheel_writer.rs b/src/module_writer/wheel_writer.rs index c3874f888..f47ee4c24 100644 --- a/src/module_writer/wheel_writer.rs +++ b/src/module_writer/wheel_writer.rs @@ -8,6 +8,7 @@ use std::path::PathBuf; use anyhow::Context as _; use anyhow::Result; use fs_err::File; +use path_slash::PathBufExt as _; use tracing::debug; use zip::ZipWriter; use zip::write::SimpleFileOptions; @@ -110,11 +111,11 @@ impl WheelWriter { self.zip.start_file_from_path(&record_filename, options)?; for (filename, (hash, len)) in self.record { - let filename = filename.to_string_lossy(); + let filename = filename.to_slash_lossy(); writeln!(self.zip, "{filename},sha256={hash},{len}")?; } // Write the record for the RECORD file itself - writeln!(self.zip, "{},,", record_filename.display())?; + writeln!(self.zip, "{},,", record_filename.to_slash_lossy())?; let file = self.zip.finish()?; Ok(file.into_path()) diff --git a/tests/common/other.rs b/tests/common/other.rs index e67dc0c3a..a293393bb 100644 --- a/tests/common/other.rs +++ b/tests/common/other.rs @@ -307,6 +307,19 @@ pub fn check_wheel_mtimes( Ok(()) } +pub fn check_wheel_paths( + package: impl AsRef, + record_file: &str, + unique_name: &str, +) -> Result<()> { + let mut wheel = build_wheel_files(package, unique_name)?; + let mut f = wheel.by_path(record_file)?; + let mut s = String::new(); + f.read_to_string(&mut s)?; + assert!(!s.contains("\\")); + Ok(()) +} + pub fn check_wheel_files( package: impl AsRef, expected_files: Vec<&str>, diff --git a/tests/run.rs b/tests/run.rs index 26819c125..0066a181f 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -951,6 +951,17 @@ fn pyo3_mixed_include_exclude_wheel_files() { )) } +// Tests that paths in the wheel `RECORD` use `/` instead of `\\`. Even +// (especially, exclusively) on Windows. +#[test] +fn pyo3_wheel_record_has_normalized_paths() { + handle_result(other::check_wheel_paths( + "test-crates/pyo3-mixed-include-exclude", + "pyo3_mixed_include_exclude-2.1.3.dist-info/RECORD", + "wheel-files-pyo3-mixed-include-exclude", + )) +} + #[test] fn workspace_sdist() { handle_result(other::test_source_distribution(