fix: always write slash paths to RECORD file (#10164)

Signed-off-by: Frost Ming <me@frostming.com>

<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR solves an issue on Windows that platform-specific paths are
written to the `RECORD` file when installing, which is inconsistent with
PEP 376, quoting:

> Each record is composed of three elements:
>
>the file’s path
> * a ‘/’-separated path, relative to the base location, if the file is
under the base location.
> * a ‘/’-separated path, relative to the base location, if the file is
under the installation prefix AND if the base location is a subpath of
the installation prefix.
> * an absolute path, using the local platform separator

## Test Plan

<!-- How was it tested? -->
Test case included

---------

Signed-off-by: Frost Ming <me@frostming.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
Frost Ming 2024-12-26 22:33:32 +08:00 committed by GitHub
parent 20df970a56
commit e6126ce0dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 8 deletions

View File

@ -604,7 +604,7 @@ pub(crate) fn write_file_recorded(
let hash = Sha256::new().chain_update(content.as_ref()).finalize();
let encoded_hash = format!("sha256={}", BASE64URL_NOPAD.encode(&hash));
record.push(RecordEntry {
path: relative_path.display().to_string(),
path: relative_path.portable_display().to_string(),
hash: Some(encoded_hash),
size: Some(content.as_ref().len() as u64),
});
@ -741,7 +741,8 @@ mod test {
use crate::Error;
use super::{
get_script_executable, parse_email_message_file, parse_wheel_file, read_record_file, Script,
get_script_executable, parse_email_message_file, parse_wheel_file, read_record_file,
write_installer_metadata, RecordEntry, Script,
};
#[test]
@ -1016,4 +1017,36 @@ mod test {
Ok(())
}
#[test]
fn test_write_installer_metadata() {
let temp_dir = assert_fs::TempDir::new().unwrap();
let site_packages = temp_dir.path();
let mut record: Vec<RecordEntry> = Vec::new();
temp_dir
.child("foo-0.1.0.dist-info")
.create_dir_all()
.unwrap();
write_installer_metadata(
site_packages,
"foo-0.1.0",
true,
None,
None,
Some("uv"),
&mut record,
)
.unwrap();
let expected = [
"foo-0.1.0.dist-info/REQUESTED",
"foo-0.1.0.dist-info/INSTALLER",
]
.map(ToString::to_string)
.to_vec();
let actual = record
.into_iter()
.map(|entry| entry.path)
.collect::<Vec<String>>();
assert_eq!(expected, actual);
}
}

View File

@ -418,12 +418,11 @@ pub fn entrypoint_paths(
};
let absolute_path = layout.scheme.scripts.join(path_in_scripts);
let script_name = entry
.path
.rsplit(std::path::MAIN_SEPARATOR)
.next()
.unwrap_or(&entry.path)
.to_string();
let script_name = relative_path
.file_name()
.and_then(|filename| filename.to_str())
.map(ToString::to_string)
.unwrap_or(entry.path);
entrypoints.push((script_name, absolute_path));
}