Deterministically order --find-links distributions (#16446)

Made to address this comment:
https://github.com/astral-sh/uv/pull/16103#discussion_r2437498249

This PR sorts the distributions collected by
`FlatIndexClient::read_from_directory` (used for `--find-links`) so
results are ordered deterministically by filename and index.
This commit is contained in:
liam 2025-10-26 21:53:32 -04:00 committed by GitHub
parent ce7808d0cb
commit ae6607d5dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 59 additions and 0 deletions

1
Cargo.lock generated
View file

@ -5668,6 +5668,7 @@ dependencies = [
"serde",
"serde_json",
"sys-info",
"tempfile",
"thiserror 2.0.17",
"tl",
"tokio",

View file

@ -74,3 +74,4 @@ hyper-util = { workspace = true }
insta = { workspace = true }
tokio = { workspace = true }
wiremock = { workspace = true }
tempfile = { workspace = true }

View file

@ -321,6 +321,63 @@ impl<'a> FlatIndexClient<'a> {
index: flat_index.clone(),
});
}
dists.sort_by(|a, b| {
a.filename
.cmp(&b.filename)
.then_with(|| a.index.cmp(&b.index))
});
Ok(FlatIndexEntries::from_entries(dists))
}
}
#[cfg(test)]
mod tests {
use super::*;
use fs_err::File;
use std::io::Write;
use tempfile::tempdir;
#[test]
fn read_from_directory_sorts_distributions() {
let dir = tempdir().unwrap();
let filenames = [
"beta-2.0.0-py3-none-any.whl",
"alpha-1.0.0.tar.gz",
"alpha-1.0.0-py3-none-any.whl",
];
for name in &filenames {
let mut file = File::create(dir.path().join(name)).unwrap();
file.write_all(b"").unwrap();
}
let entries = FlatIndexClient::read_from_directory(
dir.path(),
&IndexUrl::parse(&dir.path().to_string_lossy(), None).unwrap(),
)
.unwrap();
let actual = entries
.entries
.iter()
.map(|entry| entry.filename.to_string())
.collect::<Vec<_>>();
let mut expected = filenames
.iter()
.map(|name| DistFilename::try_from_normalized_filename(name).unwrap())
.collect::<Vec<_>>();
expected.sort();
let expected = expected
.into_iter()
.map(|filename| filename.to_string())
.collect::<Vec<_>>();
assert_eq!(actual, expected);
}
}