Skip to content

Commit b4cdb55

Browse files
authored
fix: Sparse URLs in TomlLockfileSourceId (#15990)
### What does this PR try to resolve? Sparse registries have their IDs prefixed with their kind (sparse+). This PR fixes the current implementation of `TomlLockfileSourceId` where it incorrectly splits the kind and URL for sparse registries. This change itself shouldn't affect cargo. It does, however, affect users of `cargo-util-schemas`, i.e. cargo plumbing commands. See crate-ci/cargo-plumbing#111 ### How to test and review this PR? Verify how source IDs are made, especially their URLs.
2 parents 15699ea + 00085c1 commit b4cdb55

File tree

1 file changed

+87
-3
lines changed

1 file changed

+87
-3
lines changed

crates/cargo-util-schemas/src/lockfile.rs

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,13 @@ impl TomlLockfileSourceId {
109109
EncodableSourceIdError(EncodableSourceIdErrorKind::InvalidSource(source.clone()).into())
110110
})?;
111111

112-
let url = Url::parse(url).map_err(|msg| EncodableSourceIdErrorKind::InvalidUrl {
113-
url: url.to_string(),
114-
msg: msg.to_string(),
112+
// Sparse URLs store the kind prefix (sparse+) in the URL. Therefore, for sparse kinds, we
113+
// want to use the raw `source` instead of the splitted `url`.
114+
let url = Url::parse(if kind == "sparse" { &source } else { url }).map_err(|msg| {
115+
EncodableSourceIdErrorKind::InvalidUrl {
116+
url: url.to_string(),
117+
msg: msg.to_string(),
118+
}
115119
})?;
116120

117121
let kind = match kind {
@@ -317,3 +321,83 @@ fn dump_lockfile_schema() {
317321
let dump = serde_json::to_string_pretty(&schema).unwrap();
318322
snapbox::assert_data_eq!(dump, snapbox::file!("../lockfile.schema.json").raw());
319323
}
324+
325+
#[cfg(test)]
326+
mod tests {
327+
use crate::core::{GitReference, SourceKind};
328+
use crate::lockfile::{EncodableSourceIdErrorKind, TomlLockfileSourceId};
329+
330+
#[track_caller]
331+
fn ok(source_str: &str, source_kind: SourceKind, url: &str) {
332+
let source_str = source_str.to_owned();
333+
let source_id = TomlLockfileSourceId::new(source_str).unwrap();
334+
assert_eq!(source_id.kind, source_kind);
335+
assert_eq!(source_id.url().to_string(), url);
336+
}
337+
338+
macro_rules! err {
339+
($src:expr, $expected:pat) => {
340+
let kind = TomlLockfileSourceId::new($src.to_owned()).unwrap_err().0;
341+
assert!(
342+
matches!(kind, $expected),
343+
"`{}` parse error mismatch, got {kind:?}",
344+
$src,
345+
);
346+
};
347+
}
348+
349+
#[test]
350+
fn good_sources() {
351+
ok(
352+
"sparse+https://my-crates.io",
353+
SourceKind::SparseRegistry,
354+
"sparse+https://my-crates.io",
355+
);
356+
ok(
357+
"registry+https://github.com/rust-lang/crates.io-index",
358+
SourceKind::Registry,
359+
"https://github.com/rust-lang/crates.io-index",
360+
);
361+
ok(
362+
"git+https://github.com/rust-lang/cargo",
363+
SourceKind::Git(GitReference::DefaultBranch),
364+
"https://github.com/rust-lang/cargo",
365+
);
366+
ok(
367+
"git+https://github.com/rust-lang/cargo?branch=dev",
368+
SourceKind::Git(GitReference::Branch("dev".to_owned())),
369+
"https://github.com/rust-lang/cargo?branch=dev",
370+
);
371+
ok(
372+
"git+https://github.com/rust-lang/cargo?tag=v1.0",
373+
SourceKind::Git(GitReference::Tag("v1.0".to_owned())),
374+
"https://github.com/rust-lang/cargo?tag=v1.0",
375+
);
376+
ok(
377+
"git+https://github.com/rust-lang/cargo?rev=refs/pull/493/head",
378+
SourceKind::Git(GitReference::Rev("refs/pull/493/head".to_owned())),
379+
"https://github.com/rust-lang/cargo?rev=refs/pull/493/head",
380+
);
381+
ok(
382+
"path+file:///path/to/root",
383+
SourceKind::Path,
384+
"file:///path/to/root",
385+
);
386+
}
387+
388+
#[test]
389+
fn bad_sources() {
390+
err!(
391+
"unknown+https://my-crates.io",
392+
EncodableSourceIdErrorKind::UnsupportedSource(..)
393+
);
394+
err!(
395+
"registry+https//github.com/rust-lang/crates.io-index",
396+
EncodableSourceIdErrorKind::InvalidUrl { .. }
397+
);
398+
err!(
399+
"https//github.com/rust-lang/crates.io-index",
400+
EncodableSourceIdErrorKind::InvalidSource(..)
401+
);
402+
}
403+
}

0 commit comments

Comments
 (0)