mirror of https://github.com/astral-sh/uv
Fix uv_build wheel hashes (#15400)
<!-- 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 <!-- What's the purpose of the change? What does it do, and why? --> Currently record hashes are the hex encoded sha-256 sum. However, they're supposed to be urlsafe-base64-nopad. https://packaging.python.org/en/latest/specifications/recording-installed-packages/#the-record-file Fixes #15398 ## Test Plan <!-- How was it tested? --> Build any wheel ``` uv build --wheel ``` Unpack the wheel ``` uvx wheel unpack dist/*.whl ``` Before this change, it will fail with a hash mismatch. I could confirm with a local build that now the wheel can be unpacked with the `wheel` command. While I don't enable hash checking when syncing, presumably it would also currently fail.
This commit is contained in:
parent
f1a023d384
commit
8d6ea3f2ea
|
|
@ -5167,6 +5167,7 @@ dependencies = [
|
|||
name = "uv-build-backend"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"csv",
|
||||
"flate2",
|
||||
"fs-err",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ uv-pypi-types = { workspace = true }
|
|||
uv-version = { workspace = true }
|
||||
uv-warnings = { workspace = true }
|
||||
|
||||
base64 = { workspace = true }
|
||||
csv = { workspace = true }
|
||||
flate2 = { workspace = true, default-features = false }
|
||||
fs-err = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -622,7 +622,7 @@ mod tests {
|
|||
// Check that the wheel is reproducible across platforms.
|
||||
assert_snapshot!(
|
||||
format!("{:x}", sha2::Sha256::digest(fs_err::read(&wheel_path).unwrap())),
|
||||
@"342bf60c8406144f459358cde92408686c1631fe22389d042ce80379e589d6ec"
|
||||
@"319afb04e87caf894b1362b508ec745253c6d241423ea59021694d2015e821da"
|
||||
);
|
||||
assert_snapshot!(build.wheel_contents.join("\n"), @r"
|
||||
built_by_uv-0.1.0.data/data/
|
||||
|
|
@ -665,6 +665,31 @@ mod tests {
|
|||
built_by_uv-0.1.0.dist-info/entry_points.txt (generated)
|
||||
built_by_uv-0.1.0.dist-info/METADATA (generated)
|
||||
");
|
||||
|
||||
let mut wheel = zip::ZipArchive::new(File::open(wheel_path).unwrap()).unwrap();
|
||||
let mut record = String::new();
|
||||
wheel
|
||||
.by_name("built_by_uv-0.1.0.dist-info/RECORD")
|
||||
.unwrap()
|
||||
.read_to_string(&mut record)
|
||||
.unwrap();
|
||||
assert_snapshot!(record, @r###"
|
||||
built_by_uv/__init__.py,sha256=AJ7XpTNWxYktP97ydb81UpnNqoebH7K4sHRakAMQKG4,44
|
||||
built_by_uv/arithmetic/__init__.py,sha256=x2agwFbJAafc9Z6TdJ0K6b6bLMApQdvRSQjP4iy7IEI,67
|
||||
built_by_uv/arithmetic/circle.py,sha256=FYZkv6KwrF9nJcwGOKigjke1dm1Fkie7qW1lWJoh3AE,287
|
||||
built_by_uv/arithmetic/pi.txt,sha256=-4HqoLoIrSKGf0JdTrM8BTTiIz8rq-MSCDL6LeF0iuU,8
|
||||
built_by_uv/cli.py,sha256=Jcm3PxSb8wTAN3dGm5vKEDQwCgoUXkoeggZeF34QyKM,44
|
||||
built_by_uv-0.1.0.dist-info/licenses/LICENSE-APACHE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
||||
built_by_uv-0.1.0.dist-info/licenses/LICENSE-MIT,sha256=F5Z0Cpu8QWyblXwXhrSo0b9WmYXQxd1LwLjVLJZwbiI,1077
|
||||
built_by_uv-0.1.0.dist-info/licenses/third-party-licenses/PEP-401.txt,sha256=KN-KAx829G2saLjVmByc08RFFtIDWvHulqPyD0qEBZI,270
|
||||
built_by_uv-0.1.0.data/headers/built_by_uv.h,sha256=p5-HBunJ1dY-xd4dMn03PnRClmGyRosScIp8rT46kg4,144
|
||||
built_by_uv-0.1.0.data/scripts/whoami.sh,sha256=T2cmhuDFuX-dTkiSkuAmNyIzvv8AKopjnuTCcr9o-eE,20
|
||||
built_by_uv-0.1.0.data/data/data.csv,sha256=7z7u-wXu7Qr2eBZFVpBILlNUiGSngv_1vYqZHVWOU94,265
|
||||
built_by_uv-0.1.0.dist-info/WHEEL,sha256=PaG_oOj9G2zCRqoLK0SjWBVZbGAMtIXDmm-MEGw9Wo0,83
|
||||
built_by_uv-0.1.0.dist-info/entry_points.txt,sha256=-IO6yaq6x6HSl-zWH96rZmgYvfyHlH00L5WQoCpz-YI,50
|
||||
built_by_uv-0.1.0.dist-info/METADATA,sha256=m6EkVvKrGmqx43b_VR45LHD37IZxPYC0NI6Qx9_UXLE,474
|
||||
built_by_uv-0.1.0.dist-info/RECORD,,
|
||||
"###);
|
||||
}
|
||||
|
||||
/// Test that `license = { file = "LICENSE" }` is supported.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use base64::{Engine, prelude::BASE64_URL_SAFE_NO_PAD as base64};
|
||||
use fs_err::File;
|
||||
use globset::{GlobSet, GlobSetBuilder};
|
||||
use itertools::Itertools;
|
||||
|
|
@ -346,7 +347,7 @@ struct RecordEntry {
|
|||
///
|
||||
/// While the spec would allow backslashes, we always use portable paths with forward slashes.
|
||||
path: String,
|
||||
/// The SHA256 of the files.
|
||||
/// The urlsafe-base64-nopad encoded SHA256 of the files.
|
||||
hash: String,
|
||||
/// The size of the file in bytes.
|
||||
size: usize,
|
||||
|
|
@ -381,7 +382,7 @@ fn write_hashed(
|
|||
}
|
||||
Ok(RecordEntry {
|
||||
path: path.to_string(),
|
||||
hash: format!("{:x}", hasher.finalize()),
|
||||
hash: base64.encode(hasher.finalize()),
|
||||
size,
|
||||
})
|
||||
}
|
||||
|
|
@ -641,7 +642,7 @@ impl DirectoryWriter for ZipDirectoryWriter {
|
|||
self.writer.start_file(path, options)?;
|
||||
self.writer.write_all(bytes)?;
|
||||
|
||||
let hash = format!("{:x}", Sha256::new().chain_update(bytes).finalize());
|
||||
let hash = base64.encode(Sha256::new().chain_update(bytes).finalize());
|
||||
self.record.push(RecordEntry {
|
||||
path: path.to_string(),
|
||||
hash,
|
||||
|
|
@ -719,7 +720,7 @@ impl FilesystemWriter {
|
|||
impl DirectoryWriter for FilesystemWriter {
|
||||
fn write_bytes(&mut self, path: &str, bytes: &[u8]) -> Result<(), Error> {
|
||||
trace!("Adding {}", path);
|
||||
let hash = format!("{:x}", Sha256::new().chain_update(bytes).finalize());
|
||||
let hash = base64.encode(Sha256::new().chain_update(bytes).finalize());
|
||||
self.record.push(RecordEntry {
|
||||
path: path.to_string(),
|
||||
hash,
|
||||
|
|
@ -795,14 +796,14 @@ mod test {
|
|||
fn test_record() {
|
||||
let record = vec![RecordEntry {
|
||||
path: "built_by_uv/__init__.py".to_string(),
|
||||
hash: "89f869e53a3a0061a52c0233e6442d4d72de80a8a2d3406d9ea0bfd397ed7865".to_string(),
|
||||
hash: "ifhp5To6AGGlLAIz5kQtTXLegKii00BtnqC_05fteGU".to_string(),
|
||||
size: 37,
|
||||
}];
|
||||
|
||||
let mut writer = Vec::new();
|
||||
write_record(&mut writer, "built_by_uv-0.1.0", record).unwrap();
|
||||
assert_snapshot!(String::from_utf8(writer).unwrap(), @r"
|
||||
built_by_uv/__init__.py,sha256=89f869e53a3a0061a52c0233e6442d4d72de80a8a2d3406d9ea0bfd397ed7865,37
|
||||
built_by_uv/__init__.py,sha256=ifhp5To6AGGlLAIz5kQtTXLegKii00BtnqC_05fteGU,37
|
||||
built_by_uv-0.1.0/RECORD,,
|
||||
");
|
||||
}
|
||||
|
|
@ -861,9 +862,9 @@ mod test {
|
|||
.path()
|
||||
.join("built_by_uv-0.1.0.dist-info/RECORD");
|
||||
assert_snapshot!(fs_err::read_to_string(record_file).unwrap(), @r###"
|
||||
built_by_uv-0.1.0.dist-info/WHEEL,sha256=3da1bfa0e8fd1b6cc246aa0b2b44a35815596c600cb485c39a6f8c106c3d5a8d,83
|
||||
built_by_uv-0.1.0.dist-info/entry_points.txt,sha256=f883bac9aabac7a1d297ecd61fdeab666818bdfc87947d342f9590a02a73f982,50
|
||||
built_by_uv-0.1.0.dist-info/METADATA,sha256=9ba12456f2ab1a6ab1e376ff551e392c70f7ec86713d80b4348e90c7dfd45cb1,474
|
||||
built_by_uv-0.1.0.dist-info/WHEEL,sha256=PaG_oOj9G2zCRqoLK0SjWBVZbGAMtIXDmm-MEGw9Wo0,83
|
||||
built_by_uv-0.1.0.dist-info/entry_points.txt,sha256=-IO6yaq6x6HSl-zWH96rZmgYvfyHlH00L5WQoCpz-YI,50
|
||||
built_by_uv-0.1.0.dist-info/METADATA,sha256=m6EkVvKrGmqx43b_VR45LHD37IZxPYC0NI6Qx9_UXLE,474
|
||||
built_by_uv-0.1.0.dist-info/RECORD,,
|
||||
"###);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue