Skip to content

Commit 56f6816

Browse files
committed
Add new SourceKind::SparseRegistry to differentiate sparse registries
1 parent e691e18 commit 56f6816

File tree

4 files changed

+60
-33
lines changed

4 files changed

+60
-33
lines changed

src/cargo/core/source/source_id.rs

+54-23
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ enum SourceKind {
5555
Path,
5656
/// A remote registry.
5757
Registry,
58+
/// A sparse registry.
59+
SparseRegistry,
5860
/// A local filesystem-based registry.
5961
LocalRegistry,
6062
/// A directory-based registry.
@@ -100,6 +102,20 @@ impl SourceId {
100102
SourceId { inner }
101103
}
102104

105+
fn remote_source_kind(url: &Url) -> (SourceKind, Url) {
106+
if url.as_str().starts_with("sparse+") {
107+
let url = url
108+
.to_string()
109+
.strip_prefix("sparse+")
110+
.expect("we just found that prefix")
111+
.into_url()
112+
.expect("a valid url without a protocol specifier should still be valid");
113+
(SourceKind::SparseRegistry, url)
114+
} else {
115+
(SourceKind::Registry, url.to_owned())
116+
}
117+
}
118+
103119
/// Parses a source URL and returns the corresponding ID.
104120
///
105121
/// ## Example
@@ -142,8 +158,8 @@ impl SourceId {
142158
.with_precise(Some("locked".to_string())))
143159
}
144160
"sparse" => {
145-
let url = string.into_url()?;
146-
Ok(SourceId::new(SourceKind::Registry, url, None)?
161+
let url = url.into_url()?;
162+
Ok(SourceId::new(SourceKind::SparseRegistry, url, None)?
147163
.with_precise(Some("locked".to_string())))
148164
}
149165
"path" => {
@@ -180,12 +196,14 @@ impl SourceId {
180196
/// Use [`SourceId::for_alt_registry`] if a name can provided, which
181197
/// generates better messages for cargo.
182198
pub fn for_registry(url: &Url) -> CargoResult<SourceId> {
183-
SourceId::new(SourceKind::Registry, url.clone(), None)
199+
let (kind, url) = Self::remote_source_kind(url);
200+
SourceId::new(kind, url, None)
184201
}
185202

186203
/// Creates a `SourceId` from a remote registry URL with given name.
187204
pub fn for_alt_registry(url: &Url, name: &str) -> CargoResult<SourceId> {
188-
SourceId::new(SourceKind::Registry, url.clone(), Some(name))
205+
let (kind, url) = Self::remote_source_kind(url);
206+
SourceId::new(kind, url, Some(name))
189207
}
190208

191209
/// Creates a SourceId from a local registry path.
@@ -218,7 +236,7 @@ impl SourceId {
218236
if config.cli_unstable().sparse_registry {
219237
config.check_registry_index_not_set()?;
220238
let url = CRATES_IO_HTTP_INDEX.into_url().unwrap();
221-
SourceId::new(SourceKind::Registry, url, Some(CRATES_IO_REGISTRY))
239+
SourceId::new(SourceKind::SparseRegistry, url, Some(CRATES_IO_REGISTRY))
222240
} else {
223241
Self::crates_io(config)
224242
}
@@ -230,8 +248,9 @@ impl SourceId {
230248
return Self::crates_io(config);
231249
}
232250
let url = config.get_registry_index(key)?;
251+
let (kind, url) = Self::remote_source_kind(&url);
233252
Ok(SourceId::wrap(SourceIdInner {
234-
kind: SourceKind::Registry,
253+
kind,
235254
canonical_url: CanonicalUrl::new(&url)?,
236255
url,
237256
precise: None,
@@ -298,16 +317,24 @@ impl SourceId {
298317
pub fn is_registry(self) -> bool {
299318
matches!(
300319
self.inner.kind,
301-
SourceKind::Registry | SourceKind::LocalRegistry
320+
SourceKind::Registry | SourceKind::SparseRegistry | SourceKind::LocalRegistry
302321
)
303322
}
304323

324+
/// Returns `true` if this source is from a sparse registry.
325+
pub fn is_sparse(self) -> bool {
326+
matches!(self.inner.kind, SourceKind::SparseRegistry)
327+
}
328+
305329
/// Returns `true` if this source is a "remote" registry.
306330
///
307331
/// "remote" may also mean a file URL to a git index, so it is not
308332
/// necessarily "remote". This just means it is not `local-registry`.
309333
pub fn is_remote_registry(self) -> bool {
310-
matches!(self.inner.kind, SourceKind::Registry)
334+
matches!(
335+
self.inner.kind,
336+
SourceKind::Registry | SourceKind::SparseRegistry
337+
)
311338
}
312339

313340
/// Returns `true` if this source from a Git repository.
@@ -331,11 +358,9 @@ impl SourceId {
331358
};
332359
Ok(Box::new(PathSource::new(&path, self, config)))
333360
}
334-
SourceKind::Registry => Ok(Box::new(RegistrySource::remote(
335-
self,
336-
yanked_whitelist,
337-
config,
338-
)?)),
361+
SourceKind::Registry | SourceKind::SparseRegistry => Ok(Box::new(
362+
RegistrySource::remote(self, yanked_whitelist, config)?,
363+
)),
339364
SourceKind::LocalRegistry => {
340365
let path = match self.inner.url.to_file_path() {
341366
Ok(p) => p,
@@ -382,7 +407,7 @@ impl SourceId {
382407
/// Returns `true` if the remote registry is the standard <https://crates.io>.
383408
pub fn is_crates_io(self) -> bool {
384409
match self.inner.kind {
385-
SourceKind::Registry => {}
410+
SourceKind::Registry | SourceKind::SparseRegistry => {}
386411
_ => return false,
387412
}
388413
let url = self.inner.url.as_str();
@@ -514,7 +539,9 @@ impl fmt::Display for SourceId {
514539
Ok(())
515540
}
516541
SourceKind::Path => write!(f, "{}", url_display(&self.inner.url)),
517-
SourceKind::Registry => write!(f, "registry `{}`", self.display_registry_name()),
542+
SourceKind::Registry | SourceKind::SparseRegistry => {
543+
write!(f, "registry `{}`", self.display_registry_name())
544+
}
518545
SourceKind::LocalRegistry => write!(f, "registry `{}`", url_display(&self.inner.url)),
519546
SourceKind::Directory => write!(f, "dir {}", url_display(&self.inner.url)),
520547
}
@@ -628,6 +655,10 @@ impl Ord for SourceKind {
628655
(SourceKind::Registry, _) => Ordering::Less,
629656
(_, SourceKind::Registry) => Ordering::Greater,
630657

658+
(SourceKind::SparseRegistry, SourceKind::SparseRegistry) => Ordering::Equal,
659+
(SourceKind::SparseRegistry, _) => Ordering::Less,
660+
(_, SourceKind::SparseRegistry) => Ordering::Greater,
661+
631662
(SourceKind::LocalRegistry, SourceKind::LocalRegistry) => Ordering::Equal,
632663
(SourceKind::LocalRegistry, _) => Ordering::Less,
633664
(_, SourceKind::LocalRegistry) => Ordering::Greater,
@@ -699,14 +730,14 @@ impl<'a> fmt::Display for SourceIdAsUrl<'a> {
699730
ref url,
700731
..
701732
} => {
702-
// For sparse http registry the URL already contains the prefix.
703-
if url.scheme().starts_with("sparse+") {
704-
// e.g. sparse+http://example.com
705-
write!(f, "{url}")
706-
} else {
707-
// e.g. registry+http://example.com
708-
write!(f, "registry+{url}")
709-
}
733+
write!(f, "registry+{url}")
734+
}
735+
SourceIdInner {
736+
kind: SourceKind::SparseRegistry,
737+
ref url,
738+
..
739+
} => {
740+
write!(f, "sparse+{url}")
710741
}
711742
SourceIdInner {
712743
kind: SourceKind::LocalRegistry,

src/cargo/sources/registry/http_remote.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::sources::registry::MaybeLock;
99
use crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData};
1010
use crate::util::errors::{CargoResult, HttpNotSuccessful};
1111
use crate::util::network::Retry;
12-
use crate::util::{internal, Config, Filesystem, IntoUrl, Progress, ProgressStyle};
12+
use crate::util::{internal, Config, Filesystem, Progress, ProgressStyle};
1313
use anyhow::Context;
1414
use cargo_util::paths;
1515
use curl::easy::{HttpVersion, List};
@@ -137,19 +137,15 @@ impl<'cfg> HttpRegistry<'cfg> {
137137
let url = source_id.url().as_str();
138138
// Ensure the url ends with a slash so we can concatenate paths.
139139
if !url.ends_with('/') {
140-
anyhow::bail!("registry url must end in a slash `/`: {url}")
140+
anyhow::bail!("sparse registry url must end in a slash `/`: sparse+{url}")
141141
}
142-
let url = url
143-
.trim_start_matches("sparse+")
144-
.into_url()
145-
.expect("a url with the protocol stripped should still be valid");
146142

147143
Ok(HttpRegistry {
148144
index_path: config.registry_index_path().join(name),
149145
cache_path: config.registry_cache_path().join(name),
150146
source_id,
151147
config,
152-
url,
148+
url: source_id.url().to_owned(),
153149
multi: Multi::new(),
154150
multiplexing: false,
155151
downloads: Downloads {

src/cargo/sources/registry/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ impl<'cfg> RegistrySource<'cfg> {
549549
config: &'cfg Config,
550550
) -> CargoResult<RegistrySource<'cfg>> {
551551
let name = short_name(source_id);
552-
let ops = if source_id.url().scheme().starts_with("sparse+") {
552+
let ops = if source_id.is_sparse() {
553553
Box::new(http_remote::HttpRegistry::new(source_id, config, &name)?) as Box<_>
554554
} else {
555555
Box::new(remote::RemoteRegistry::new(source_id, config, &name)) as Box<_>

tests/testsuite/registry.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2705,10 +2705,10 @@ fn http_requires_z_flag() {
27052705

27062706
#[cargo_test]
27072707
fn http_requires_trailing_slash() {
2708-
cargo_process("-Z sparse-registry install bar --index sparse+https://index.crates.io")
2708+
cargo_process("-Z sparse-registry install bar --index sparse+https://invalid.crates.io/test")
27092709
.masquerade_as_nightly_cargo(&["sparse-registry"])
27102710
.with_status(101)
2711-
.with_stderr("[ERROR] registry url must end in a slash `/`: sparse+https://index.crates.io")
2711+
.with_stderr("[ERROR] sparse registry url must end in a slash `/`: sparse+https://invalid.crates.io/test")
27122712
.run()
27132713
}
27142714

0 commit comments

Comments
 (0)