mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-01 12:24:15 +00:00
feat(publish): include blake2b hash in upload form (#15794)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / integration test | activate nushell venv (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | pyenv on wsl x86-64 (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | x86-64 python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / test windows trampoline | aarch64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux aarch64 (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / smoke test | linux aarch64 (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / integration test | activate nushell venv (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | pyenv on wsl x86-64 (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / build binary | msrv (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | x86-64 python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
zizmor / Run zizmor (push) Waiting to run
This commit is contained in:
parent
a0f8359012
commit
21a92c1632
1 changed files with 41 additions and 14 deletions
|
|
@ -584,14 +584,14 @@ pub async fn check_url(
|
|||
if let Some(remote_hash) = archived_file.hashes.first() {
|
||||
// We accept the risk for TOCTOU errors here, since we already read the file once before the
|
||||
// streaming upload to compute the hash for the form metadata.
|
||||
let local_hash = hash_file(file, Hasher::from(remote_hash.algorithm))
|
||||
let local_hash = &hash_file(file, vec![Hasher::from(remote_hash.algorithm)])
|
||||
.await
|
||||
.map_err(|err| {
|
||||
PublishError::PublishPrepare(
|
||||
file.to_path_buf(),
|
||||
Box::new(PublishPrepareError::Io(err)),
|
||||
)
|
||||
})?;
|
||||
})?[0];
|
||||
if local_hash.digest == remote_hash.digest {
|
||||
debug!(
|
||||
"Found {filename} in the registry with matching hash {}",
|
||||
|
|
@ -611,13 +611,20 @@ pub async fn check_url(
|
|||
}
|
||||
}
|
||||
|
||||
/// Calculate the SHA256 of a file.
|
||||
async fn hash_file(path: impl AsRef<Path>, hasher: Hasher) -> Result<HashDigest, io::Error> {
|
||||
/// Calculate the requested hashes of a file.
|
||||
async fn hash_file(
|
||||
path: impl AsRef<Path>,
|
||||
hashers: Vec<Hasher>,
|
||||
) -> Result<Vec<HashDigest>, io::Error> {
|
||||
debug!("Hashing {}", path.as_ref().display());
|
||||
let file = BufReader::new(File::open(path.as_ref()).await?);
|
||||
let mut hashers = vec![hasher];
|
||||
let mut hashers = hashers;
|
||||
HashReader::new(file, &mut hashers).finish().await?;
|
||||
Ok(HashDigest::from(hashers.remove(0)))
|
||||
|
||||
Ok(hashers
|
||||
.into_iter()
|
||||
.map(HashDigest::from)
|
||||
.collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
// Not in `uv-metadata` because we only support tar files here.
|
||||
|
|
@ -693,7 +700,24 @@ impl FormMetadata {
|
|||
file: &Path,
|
||||
filename: &DistFilename,
|
||||
) -> Result<Self, PublishPrepareError> {
|
||||
let hash_hex = hash_file(file, Hasher::from(HashAlgorithm::Sha256)).await?;
|
||||
let hashes = hash_file(
|
||||
file,
|
||||
vec![
|
||||
Hasher::from(HashAlgorithm::Sha256),
|
||||
Hasher::from(HashAlgorithm::Blake2b),
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
|
||||
let sha256_hash = hashes
|
||||
.iter()
|
||||
.find(|hash| hash.algorithm == HashAlgorithm::Sha256)
|
||||
.unwrap();
|
||||
|
||||
let blake2b_hash = hashes
|
||||
.iter()
|
||||
.find(|hash| hash.algorithm == HashAlgorithm::Blake2b)
|
||||
.unwrap();
|
||||
|
||||
let Metadata23 {
|
||||
metadata_version,
|
||||
|
|
@ -728,7 +752,8 @@ impl FormMetadata {
|
|||
|
||||
let mut form_metadata = vec![
|
||||
(":action", "file_upload".to_string()),
|
||||
("sha256_digest", hash_hex.digest.to_string()),
|
||||
("sha256_digest", sha256_hash.digest.to_string()),
|
||||
("blake2_256_digest", blake2b_hash.digest.to_string()),
|
||||
("protocol_version", "1".to_string()),
|
||||
("metadata_version", metadata_version.clone()),
|
||||
// Twine transforms the name with `re.sub("[^A-Za-z0-9.]+", "-", name)`
|
||||
|
|
@ -1040,9 +1065,10 @@ mod tests {
|
|||
.iter()
|
||||
.map(|(k, v)| format!("{k}: {v}"))
|
||||
.join("\n");
|
||||
assert_snapshot!(&formatted_metadata, @r###"
|
||||
assert_snapshot!(&formatted_metadata, @r"
|
||||
:action: file_upload
|
||||
sha256_digest: 89fa05cffa7f457658373b85de302d24d0c205ceda2819a8739e324b75e9430b
|
||||
blake2_256_digest: 40ab79b48c4e289e4990f7e689177adae4096c07a634034eb1d10c0b6700e4d2
|
||||
protocol_version: 1
|
||||
metadata_version: 2.3
|
||||
name: tqdm
|
||||
|
|
@ -1088,7 +1114,7 @@ mod tests {
|
|||
project_urls: Documentation, https://github.com/unknown/tqdm#readme
|
||||
project_urls: Issues, https://github.com/unknown/tqdm/issues
|
||||
project_urls: Source, https://github.com/unknown/tqdm
|
||||
"###);
|
||||
");
|
||||
|
||||
let client = BaseClientBuilder::default().build();
|
||||
let (request, _) = build_upload_request(
|
||||
|
|
@ -1128,7 +1154,7 @@ mod tests {
|
|||
},
|
||||
headers: {
|
||||
"content-type": "multipart/form-data; boundary=[...]",
|
||||
"content-length": "6803",
|
||||
"content-length": "7000",
|
||||
"accept": "application/json;q=0.9, text/plain;q=0.8, text/html;q=0.7",
|
||||
"authorization": Sensitive,
|
||||
},
|
||||
|
|
@ -1154,9 +1180,10 @@ mod tests {
|
|||
.iter()
|
||||
.map(|(k, v)| format!("{k}: {v}"))
|
||||
.join("\n");
|
||||
assert_snapshot!(&formatted_metadata, @r###"
|
||||
assert_snapshot!(&formatted_metadata, @r#"
|
||||
:action: file_upload
|
||||
sha256_digest: 0d88ca657bc6b64995ca416e0c59c71af85cc10015d940fa446c42a8b485ee1c
|
||||
blake2_256_digest: 33d4e92517a16e3fa0c0893de0c7e4d46a2c38adab148dd2ff66eb47481d19cd
|
||||
protocol_version: 1
|
||||
metadata_version: 2.1
|
||||
name: tqdm
|
||||
|
|
@ -1240,7 +1267,7 @@ mod tests {
|
|||
requires_dist: ipywidgets >=6 ; extra == 'notebook'
|
||||
requires_dist: slack-sdk ; extra == 'slack'
|
||||
requires_dist: requests ; extra == 'telegram'
|
||||
"###);
|
||||
"#);
|
||||
|
||||
let client = BaseClientBuilder::default().build();
|
||||
let (request, _) = build_upload_request(
|
||||
|
|
@ -1280,7 +1307,7 @@ mod tests {
|
|||
},
|
||||
headers: {
|
||||
"content-type": "multipart/form-data; boundary=[...]",
|
||||
"content-length": "19330",
|
||||
"content-length": "19527",
|
||||
"accept": "application/json;q=0.9, text/plain;q=0.8, text/html;q=0.7",
|
||||
"authorization": Sensitive,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue