Skip to content

Commit

Permalink
Add support for new index hash implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
UebelAndre committed Feb 8, 2025
1 parent 973f2e5 commit 9f63743
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ http = { version = "1", optional = true }
memchr = "2.5.0"
rayon = { version = "1.7.0", optional = true }
rustc-hash = "2.0.0"
rustc-stable-hash = "0.1.1"
semver = "1.0.17"
serde = { version = "1.0.160", features = ["rc"] }
serde_derive = "1.0.160"
Expand Down
83 changes: 73 additions & 10 deletions src/dirs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,23 @@ pub fn local_path_and_canonical_url(
url: &str,
cargo_home: Option<&std::path::Path>,
) -> Result<(std::path::PathBuf, String), Error> {
let (dir_name, canonical_url) = url_to_local_dir(url)?;

let mut path = match cargo_home {
Some(path) => path.to_owned(),
None => home::cargo_home()?,
};

path.push("registry");
path.push("index");
path.push(dir_name);

let (dir_name, canonical) = url_to_local_dir(url, true)?;
let canonical_url = if path.join(&dir_name).exists() {
path.push(dir_name);
canonical
} else {
let (dir_name, canonical) = url_to_local_dir(url, false)?;
path.push(dir_name);
canonical
};

Ok((path, canonical_url))
}
Expand Down Expand Up @@ -72,8 +79,8 @@ pub(crate) fn crate_name_to_relative_path(crate_name: &str, separator: Option<ch

/// Converts a full url, eg https://github.com/rust-lang/crates.io-index, into
/// the root directory name where cargo itself will fetch it on disk
fn url_to_local_dir(url: &str) -> Result<(String, String), Error> {
fn to_hex(num: u64) -> String {
fn url_to_local_dir(url: &str, use_stable_hash: bool) -> Result<(String, String), Error> {
fn legacy_to_hex(num: u64) -> String {
const CHARS: &[u8] = b"0123456789abcdef";

let bytes = &[
Expand Down Expand Up @@ -102,7 +109,7 @@ fn url_to_local_dir(url: &str) -> Result<(String, String), Error> {
}

#[allow(deprecated)]
fn hash_u64(url: &str, registry_kind: u64) -> u64 {
fn legacy_hash_u64(url: &str, registry_kind: u64) -> u64 {
use std::hash::{Hash, Hasher, SipHasher};

let mut hasher = SipHasher::new_with_keys(0, 0);
Expand All @@ -113,6 +120,35 @@ fn url_to_local_dir(url: &str) -> Result<(String, String), Error> {
hasher.finish()
}

fn stable_to_hex(num: u64) -> String {
hex::encode(num.to_le_bytes())
}

fn stable_hash_u64(url: &str, registry_kind: u64) -> u64 {
// Matches https://github.com/rust-lang/cargo/blob/49e5d24870a13cd3f26ad61159045788b36efcdf/src/cargo/util/hasher.rs#L6
use rustc_stable_hash::StableSipHasher128 as StableHasher;
use std::hash::{Hash, Hasher};

let mut hasher = StableHasher::new();
// Registry
registry_kind.hash(&mut hasher);
// Url
url.hash(&mut hasher);
Hasher::finish(&hasher)
}

let hash_u64 = if use_stable_hash {
stable_hash_u64
} else {
legacy_hash_u64
};

let to_hex = if use_stable_hash {
stable_to_hex
} else {
legacy_to_hex
};

// SourceKind::Registry
let mut registry_kind = 2;

Expand Down Expand Up @@ -190,35 +226,62 @@ mod test {
fn http_index_url_matches_cargo() {
use crate::sparse::URL;
assert_eq!(
super::url_to_local_dir(URL).unwrap(),
super::url_to_local_dir(URL, false).unwrap(),
("index.crates.io-6f17d22bba15001f".to_owned(), URL.to_owned(),)
);
assert_eq!(
super::url_to_local_dir(URL, true).unwrap(),
("index.crates.io-1949cf8c6b5b557f".to_owned(), URL.to_owned(),)
);

// I've confirmed this also works with a custom registry, unfortunately
// that one includes a secret key as part of the url which would allow
// anyone to publish to the registry, so uhh...here's a fake one instead
assert_eq!(
super::url_to_local_dir("https://dl.cloudsmith.io/aBcW1234aBcW1234/embark/rust/cargo/index.git").unwrap(),
super::url_to_local_dir(
"https://dl.cloudsmith.io/aBcW1234aBcW1234/embark/rust/cargo/index.git",
false
)
.unwrap(),
(
"dl.cloudsmith.io-ff79e51ddd2b38fd".to_owned(),
"https://dl.cloudsmith.io/aBcW1234aBcW1234/embark/rust/cargo/index.git".to_owned()
)
);
assert_eq!(
super::url_to_local_dir(
"https://dl.cloudsmith.io/aBcW1234aBcW1234/embark/rust/cargo/index.git",
true
)
.unwrap(),
(
"dl.cloudsmith.io-fade991491aaf150".to_owned(),
"https://dl.cloudsmith.io/aBcW1234aBcW1234/embark/rust/cargo/index.git".to_owned()
)
);
}

#[test]
#[cfg(feature = "git")]
fn git_url_matches_cargo() {
use crate::git::URL;
assert_eq!(
crate::dirs::url_to_local_dir(URL).unwrap(),
crate::dirs::url_to_local_dir(URL, false).unwrap(),
("github.com-1ecc6299db9ec823".to_owned(), URL.to_owned())
);
assert_eq!(
crate::dirs::url_to_local_dir(URL, true).unwrap(),
("github.com-1ecc6299db9ec823".to_owned(), URL.to_owned())
);

// Ensure we actually strip off the irrelevant parts of a url, note that
// the .git suffix is not part of the canonical url, but *is* used when hashing
assert_eq!(
crate::dirs::url_to_local_dir(&format!("registry+{}.git?one=1&two=2#fragment", URL)).unwrap(),
crate::dirs::url_to_local_dir(&format!("registry+{}.git?one=1&two=2#fragment", URL), false).unwrap(),
("github.com-c786010fb7ef2e6e".to_owned(), URL.to_owned())
);
assert_eq!(
crate::dirs::url_to_local_dir(&format!("registry+{}.git?one=1&two=2#fragment", URL), true).unwrap(),
("github.com-c786010fb7ef2e6e".to_owned(), URL.to_owned())
);
}
Expand Down

0 comments on commit 9f63743

Please sign in to comment.