-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The goal is to keep related code together, instead of spreading it out into top-level modules exclusively.
- Loading branch information
Showing
9 changed files
with
745 additions
and
737 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use crate::Error; | ||
use std::path::{Path, PathBuf}; | ||
|
||
/// Calls the specified function for each cargo config located according to | ||
/// cargo's standard hierarchical structure | ||
/// | ||
/// Note that this only supports the use of `.cargo/config.toml`, which is not | ||
/// supported below cargo 1.39.0 | ||
/// | ||
/// See https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure | ||
fn read_cargo_config<T>( | ||
root: Option<&Path>, | ||
cargo_home: Option<&Path>, | ||
callback: impl Fn(&toml::Value) -> Option<T>, | ||
) -> Result<Option<T>, Error> { | ||
use std::borrow::Cow; | ||
|
||
if let Some(mut path) = root | ||
.map(PathBuf::from) | ||
.or_else(|| std::env::current_dir().ok()) | ||
{ | ||
loop { | ||
path.push(".cargo/config.toml"); | ||
if let Some(toml) = try_read_toml(&path)? { | ||
if let Some(value) = callback(&toml) { | ||
return Ok(Some(value)); | ||
} | ||
} | ||
path.pop(); | ||
path.pop(); | ||
|
||
// Walk up to the next potential config root | ||
if !path.pop() { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if let Some(home) = cargo_home | ||
.map(Cow::Borrowed) | ||
.or_else(|| home::cargo_home().ok().map(Cow::Owned)) | ||
{ | ||
let path = home.join("config.toml"); | ||
if let Some(toml) = try_read_toml(&path)? { | ||
if let Some(value) = callback(&toml) { | ||
return Ok(Some(value)); | ||
} | ||
} | ||
} | ||
|
||
Ok(None) | ||
} | ||
|
||
fn try_read_toml(path: &Path) -> Result<Option<toml::Value>, Error> { | ||
if !path.exists() { | ||
return Ok(None); | ||
} | ||
|
||
let toml = toml::from_str(&std::fs::read_to_string(path)?).map_err(Error::Toml)?; | ||
Ok(Some(toml)) | ||
} | ||
|
||
/// Gets the url of a replacement registry for crates.io if one has been configured | ||
/// | ||
/// See https://doc.rust-lang.org/cargo/reference/source-replacement.html | ||
#[inline] | ||
pub(crate) fn get_crates_io_replacement( | ||
root: Option<&Path>, | ||
cargo_home: Option<&Path>, | ||
) -> Result<Option<String>, 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(|v| v.as_str().map(String::from)) | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use gix::bstr::ByteSlice; | ||
use super::*; | ||
|
||
#[test] | ||
#[cfg_attr(debug_assertions, ignore = "too slow in debug mode")] | ||
fn parse_all_blobs() { | ||
std::thread::scope(|scope| { | ||
let (tx, rx) = std::sync::mpsc::channel(); | ||
let blobs = scope.spawn(move || { | ||
let index = shared_index(); | ||
for c in index.crates_blobs().unwrap() { | ||
tx.send(c).unwrap(); | ||
} | ||
}); | ||
let parse = scope.spawn(move || { | ||
let mut found_gcc_crate = false; | ||
let mut ctx = DedupeContext::new(); | ||
for c in rx { | ||
match c.parse(&mut ctx) { | ||
Ok(c) => { | ||
if c.name() == "gcc" { | ||
found_gcc_crate = true; | ||
} | ||
} | ||
Err(e) => panic!("can't parse :( {:?}: {e}", c.0.as_bstr()), | ||
} | ||
} | ||
assert!(found_gcc_crate); | ||
}); | ||
parse.join().unwrap(); | ||
blobs.join().unwrap(); | ||
}); | ||
} | ||
|
||
fn shared_index() -> Index { | ||
let index_path = "tests/fixtures/git-registry"; | ||
if is_ci::cached() { | ||
Index::new_cargo_default() | ||
.expect("CI has just cloned this index and its ours and valid") | ||
} else { | ||
Index::with_path(index_path, INDEX_GIT_URL).expect("clone works and there is no racing") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,44 @@ | ||
use crate::Error; | ||
use std::path::{Path, PathBuf}; | ||
|
||
/// Calls the specified function for each cargo config located according to | ||
/// cargo's standard hierarchical structure | ||
/// | ||
/// Note that this only supports the use of `.cargo/config.toml`, which is not | ||
/// supported below cargo 1.39.0 | ||
/// | ||
/// See https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure | ||
pub(crate) fn read_cargo_config<T>( | ||
root: Option<&Path>, | ||
cargo_home: Option<&Path>, | ||
callback: impl Fn(&toml::Value) -> Option<T>, | ||
) -> Result<Option<T>, Error> { | ||
use std::borrow::Cow; | ||
|
||
if let Some(mut path) = root | ||
.map(PathBuf::from) | ||
.or_else(|| std::env::current_dir().ok()) | ||
{ | ||
loop { | ||
path.push(".cargo/config.toml"); | ||
if let Some(toml) = try_read_toml(&path)? { | ||
if let Some(value) = callback(&toml) { | ||
return Ok(Some(value)); | ||
} | ||
} | ||
path.pop(); | ||
path.pop(); | ||
|
||
// Walk up to the next potential config root | ||
if !path.pop() { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if let Some(home) = cargo_home | ||
.map(Cow::Borrowed) | ||
.or_else(|| home::cargo_home().ok().map(Cow::Owned)) | ||
{ | ||
let path = home.join("config.toml"); | ||
if let Some(toml) = try_read_toml(&path)? { | ||
if let Some(value) = callback(&toml) { | ||
return Ok(Some(value)); | ||
} | ||
} | ||
} | ||
|
||
Ok(None) | ||
use serde_derive::Deserialize; | ||
use crate::dirs::crate_prefix; | ||
|
||
/// Global configuration of an index, reflecting the [contents of config.json](https://doc.rust-lang.org/cargo/reference/registries.html#index-format). | ||
#[derive(Clone, Debug, Deserialize)] | ||
pub struct IndexConfig { | ||
/// Pattern for creating download URLs. Use [`IndexConfig::download_url`] instead. | ||
pub dl: String, | ||
/// Base URL for publishing, etc. | ||
pub api: Option<String>, | ||
} | ||
|
||
fn try_read_toml(path: &Path) -> Result<Option<toml::Value>, Error> { | ||
if !path.exists() { | ||
return Ok(None); | ||
impl IndexConfig { | ||
/// Get the URL from where the specified package can be downloaded. | ||
/// This method assumes the particular version is present in the registry, | ||
/// and does not verify that it is. | ||
#[must_use] | ||
pub fn download_url(&self, name: &str, version: &str) -> Option<String> { | ||
if !self.dl.contains("{crate}") | ||
&& !self.dl.contains("{version}") | ||
&& !self.dl.contains("{prefix}") | ||
&& !self.dl.contains("{lowerprefix}") | ||
{ | ||
let mut new = String::with_capacity(self.dl.len() + name.len() + version.len() + 10); | ||
new.push_str(&self.dl); | ||
new.push('/'); | ||
new.push_str(name); | ||
new.push('/'); | ||
new.push_str(version); | ||
new.push_str("/download"); | ||
Some(new) | ||
} else { | ||
let mut prefix = String::with_capacity(5); | ||
crate_prefix(&mut prefix, name, '/')?; | ||
Some( | ||
self.dl | ||
.replace("{crate}", name) | ||
.replace("{version}", version) | ||
.replace("{prefix}", &prefix) | ||
.replace("{lowerprefix}", &prefix.to_ascii_lowercase()), | ||
) | ||
} | ||
} | ||
|
||
let toml = toml::from_str(&std::fs::read_to_string(path)?).map_err(Error::Toml)?; | ||
Ok(Some(toml)) | ||
} | ||
|
||
/// Gets the url of a replacement registry for crates.io if one has been configured | ||
/// | ||
/// See https://doc.rust-lang.org/cargo/reference/source-replacement.html | ||
#[inline] | ||
pub(crate) fn get_crates_io_replacement( | ||
root: Option<&Path>, | ||
cargo_home: Option<&Path>, | ||
) -> Result<Option<String>, 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(|v| v.as_str().map(String::from)) | ||
}) | ||
}) | ||
} |
Oops, something went wrong.