Skip to content

Commit

Permalink
Switch from toml -> toml-span (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake-Shadle authored Feb 20, 2024
1 parent 112eb41 commit 18c6583
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 91 deletions.
80 changes: 23 additions & 57 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ tokio = { version = "1.0", default-features = false, features = [
"time",
], optional = true }
# cargo config parsing
toml = "0.8"
toml-span = "0.1"
# Faster hashing
twox-hash = { version = "1.6", default-features = false }

Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub enum Error {
Json(#[from] serde_json::Error),
/// Failed to deserialize TOML
#[error(transparent)]
Toml(#[from] Box<toml::de::Error>),
Toml(#[from] Box<toml_span::Error>),
/// An index entry did not contain any versions
#[error("index entry contained no versions for the crate")]
NoCrateVersions,
Expand Down
100 changes: 68 additions & 32 deletions src/index/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,17 @@ impl<'iu> IndexUrl<'iu> {
Some("sparse") => true,
Some("git") => false,
_ => {
let sparse_index = read_cargo_config(config_root, cargo_home, |config| {
config
.get("registries")
.and_then(|v| v.get("crates-io"))
.and_then(|v| v.get("protocol"))
.and_then(|v| v.as_str())
.and_then(|v| match v {
let sparse_index =
read_cargo_config(config_root, cargo_home, |config| {
match config
.pointer("/registries/crates-io/protocol")
.and_then(|p| p.as_str())?
{
"sparse" => Some(true),
"git" => Some(false),
_ => None,
})
})?;
}
})?;

if let Some(si) = sparse_index {
si
Expand Down Expand Up @@ -196,7 +195,7 @@ impl<'il> IndexLocation<'il> {
pub(crate) fn read_cargo_config<T>(
root: Option<PathBuf>,
cargo_home: Option<&Path>,
callback: impl Fn(&toml::Value) -> Option<T>,
callback: impl Fn(&toml_span::value::Value<'_>) -> Option<T>,
) -> Result<Option<T>, Error> {
if let Some(mut path) = root.or_else(|| {
std::env::current_dir()
Expand All @@ -211,7 +210,7 @@ pub(crate) fn read_cargo_config<T>(
Err(err) => return Err(Error::IoPath(err, path)),
};

let toml: toml::Value = toml::from_str(&contents).map_err(Box::new)?;
let toml = toml_span::parse(&contents).map_err(Box::new)?;
if let Some(value) = callback(&toml) {
return Ok(Some(value));
}
Expand All @@ -232,8 +231,8 @@ pub(crate) fn read_cargo_config<T>(
{
let path = home.join("config.toml");
if path.exists() {
let toml: toml::Value =
toml::from_str(&std::fs::read_to_string(&path)?).map_err(Box::new)?;
let fc = std::fs::read_to_string(&path)?;
let toml = toml_span::parse(&fc).map_err(Box::new)?;
if let Some(value) = callback(&toml) {
return Ok(Some(value));
}
Expand All @@ -252,25 +251,19 @@ pub(crate) fn get_crates_io_replacement<'iu>(
cargo_home: Option<&Path>,
) -> Result<Option<IndexUrl<'iu>>, Error> {
read_cargo_config(root, cargo_home, |config| {
config.get("source").and_then(|sources| {
sources
.get("crates-io")
.and_then(|v| v.get("replace-with"))
.and_then(|v| v.as_str())
.and_then(|v| sources.get(v))
.and_then(|v| {
v.get("registry")
.and_then(|reg| {
reg.as_str()
.map(|r| IndexUrl::NonCratesIo(r.to_owned().into()))
})
.or_else(|| {
v.get("local-registry").and_then(|l| {
l.as_str().map(|l| IndexUrl::Local(PathBuf::from(l).into()))
})
})
})
})
let repw = config.pointer("/source/crates-io/replace-with")?.as_str()?;
let sources = config.pointer("/source")?.as_table()?;
let replace_src = sources.get(&repw.into())?.as_table()?;

if let Some(rr) = replace_src.get(&"registry".into()) {
rr.as_str()
.map(|r| IndexUrl::NonCratesIo(r.to_owned().into()))
} else if let Some(rlr) = replace_src.get(&"local-registry".into()) {
rlr.as_str()
.map(|l| IndexUrl::Local(PathBuf::from(l).into()))
} else {
None
}
})
}

Expand All @@ -288,4 +281,47 @@ mod test {
crate::index::ComboIndexCache::Sparse(_)
));
}

/// Verifies we can parse .cargo/config.toml files to either use the crates-io
/// protocol set, or source replacements
#[test]
fn parses_from_file() {
assert!(std::env::var_os("CARGO_REGISTRIES_CRATES_IO_PROTOCOL").is_none());

let td = tempfile::tempdir().unwrap();
let root = crate::PathBuf::from_path_buf(td.path().to_owned()).unwrap();
let cfg_toml = td.path().join(".cargo/config.toml");

std::fs::create_dir_all(cfg_toml.parent().unwrap()).unwrap();

const GIT: &str = r#"[registries.crates-io]
protocol = "git"
"#;

// First just set the protocol from the sparse default to git
std::fs::write(&cfg_toml, GIT).unwrap();

let iurl = super::IndexUrl::crates_io(Some(root.clone()), None, None).unwrap();
assert_eq!(iurl.as_str(), crate::CRATES_IO_INDEX);
assert!(!iurl.is_sparse());

// Next set replacement registries
for (i, (kind, url)) in [
(
"registry",
"sparse+https://sparse-registry-parses-from-file.com",
),
("registry", "https://sparse-registry-parses-from-file.git"),
("local-registry", root.as_str()),
]
.iter()
.enumerate()
{
std::fs::write(&cfg_toml, format!("{GIT}\n[source.crates-io]\nreplace-with = 'replacement'\n[source.replacement]\n{kind} = '{url}'")).unwrap();

let iurl = super::IndexUrl::crates_io(Some(root.clone()), None, None).unwrap();
assert_eq!(i == 0, iurl.is_sparse());
assert_eq!(iurl.as_str(), *url);
}
}
}
6 changes: 6 additions & 0 deletions tests/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ fn builds_local_registry() {
let ip = krates.entry(pkg.name.clone()).or_insert_with(|| {
let ik = sparse
.cached_krate(pkg.name.as_str().try_into().unwrap(), &lock)
.map_err(|e| {
panic!("failed to read cache entry for {}: {e}", pkg.name);
})
.unwrap()
.ok_or_else(|| {
panic!("no cache entry for {}", pkg.name);
})
.unwrap();

IndexPkg {
Expand Down

0 comments on commit 18c6583

Please sign in to comment.