Skip to content

Commit 4c341a4

Browse files
committed
Skip existing, second iteration
1 parent 572840d commit 4c341a4

File tree

14 files changed

+463
-219
lines changed

14 files changed

+463
-219
lines changed

Cargo.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv-cli/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4797,6 +4797,22 @@ pub struct PublishArgs {
47974797
value_parser = parse_insecure_host,
47984798
)]
47994799
pub allow_insecure_host: Option<Vec<Maybe<TrustedHost>>>,
4800+
4801+
/// Don't upload files that already exists on the index. The value is the index URL.
4802+
///
4803+
/// This option allows retrying publishing that failed after only some, but not all files have
4804+
/// been uploaded, and handles error due to parallel uploads of the same file.
4805+
///
4806+
/// Before uploading, the index is checked. If the exact same file already exists in the index,
4807+
/// the file will not be uploaded. If an error occurred during the upload, the index is checked
4808+
/// again, if the file may have been added in the meantime.
4809+
///
4810+
/// The exact behavior varies from index to index. On PyPI, uploading the same file succeeds
4811+
/// even without `--skip-existing`, while most other indexes error.
4812+
///
4813+
/// The index must provide one of the supported hashes (SHA-256, SHA-384, or SHA-512).
4814+
#[arg(long,env = EnvVars::UV_PUBLISH_SKIP_EXISTING)]
4815+
pub skip_existing: Option<IndexUrl>,
48004816
}
48014817

48024818
/// See [PEP 517](https://peps.python.org/pep-0517/) and

crates/uv-client/src/registry_client.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::time::Duration;
1212
use tracing::{info_span, instrument, trace, warn, Instrument};
1313
use url::Url;
1414

15-
use uv_cache::{Cache, CacheBucket, CacheEntry, WheelCache};
15+
use uv_cache::{Cache, CacheBucket, CacheEntry, Refresh, WheelCache};
1616
use uv_configuration::KeyringProviderType;
1717
use uv_configuration::{IndexStrategy, TrustedHost};
1818
use uv_distribution_filename::{DistFilename, SourceDistFilename, WheelFilename};
@@ -31,7 +31,7 @@ use crate::cached_client::CacheControl;
3131
use crate::html::SimpleHtml;
3232
use crate::remote_metadata::wheel_metadata_from_remote_zip;
3333
use crate::rkyvutil::OwnedArchive;
34-
use crate::{CachedClient, CachedClientError, Error, ErrorKind};
34+
use crate::{BaseClient, CachedClient, CachedClientError, Error, ErrorKind};
3535

3636
/// A builder for an [`RegistryClient`].
3737
#[derive(Debug, Clone)]
@@ -143,6 +143,27 @@ impl<'a> RegistryClientBuilder<'a> {
143143
timeout,
144144
}
145145
}
146+
147+
/// Share the underlying client between two different middleware configurations.
148+
pub fn wrap_existing(self, existing: &BaseClient) -> RegistryClient {
149+
// Wrap in any relevant middleware and handle connectivity.
150+
let client = self.base_client_builder.wrap_existing(existing);
151+
152+
let timeout = client.timeout();
153+
let connectivity = client.connectivity();
154+
155+
// Wrap in the cache middleware.
156+
let client = CachedClient::new(client);
157+
158+
RegistryClient {
159+
index_urls: self.index_urls,
160+
index_strategy: self.index_strategy,
161+
cache: self.cache,
162+
connectivity,
163+
client,
164+
timeout,
165+
}
166+
}
146167
}
147168

148169
impl<'a> TryFrom<BaseClientBuilder<'a>> for RegistryClientBuilder<'a> {
@@ -266,6 +287,11 @@ impl RegistryClient {
266287
Ok(results)
267288
}
268289

290+
/// Invalidate the cache after the index changed.
291+
pub fn refresh(&mut self, refresh: Refresh) {
292+
self.cache = self.cache.clone().with_refresh(refresh);
293+
}
294+
269295
/// Fetch the [`SimpleMetadata`] from a single index for a given package.
270296
///
271297
/// The index can either be a PEP 503-compatible remote repository, or a local directory laid

crates/uv-extract/src/hash.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,6 @@ impl Hasher {
2323
Hasher::Sha512(hasher) => hasher.update(data),
2424
}
2525
}
26-
27-
pub fn finalize(self) -> Vec<u8> {
28-
match self {
29-
Hasher::Md5(hasher) => hasher.finalize().to_vec(),
30-
Hasher::Sha256(hasher) => hasher.finalize().to_vec(),
31-
Hasher::Sha384(hasher) => hasher.finalize().to_vec(),
32-
Hasher::Sha512(hasher) => hasher.finalize().to_vec(),
33-
}
34-
}
3526
}
3627

3728
impl From<HashAlgorithm> for Hasher {

crates/uv-publish/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ license.workspace = true
1313
doctest = false
1414

1515
[dependencies]
16+
uv-cache = { workspace = true }
1617
uv-client = { workspace = true }
1718
uv-configuration = { workspace = true }
1819
uv-distribution-filename = { workspace = true }
20+
uv-distribution-types = { workspace = true }
21+
uv-extract = { workspace = true }
1922
uv-fs = { workspace = true }
2023
uv-metadata = { workspace = true }
2124
uv-pypi-types = { workspace = true }
@@ -35,7 +38,6 @@ reqwest-retry = { workspace = true }
3538
rustc-hash = { workspace = true }
3639
serde = { workspace = true, features = ["derive"] }
3740
serde_json = { workspace = true }
38-
sha2 = { workspace = true }
3941
thiserror = { workspace = true }
4042
tokio = { workspace = true }
4143
tokio-util = { workspace = true , features = ["io"] }

0 commit comments

Comments
 (0)