Skip to content

Commit

Permalink
Fix git-tag cache-key reader in case of slashes (astral-sh#10467)
Browse files Browse the repository at this point in the history
The assumption that all tags are listed under flat `.git/ref/tags`
structure was wrong. Git will make a hierarchy of directories for tags
containing slashes. To fix cache-key computation we need to recursively
traverse all files under this folder instead.
  • Loading branch information
Sergei Nizovtsev committed Jan 11, 2025
1 parent 27d1bad commit 62ba062
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/uv-cache-info/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
toml = { workspace = true }
tracing = { workspace = true }
walkdir = { workspace = true }
36 changes: 22 additions & 14 deletions crates/uv-cache-info/src/git_info.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use tracing::warn;
use walkdir::WalkDir;

#[derive(Debug, thiserror::Error)]
pub(crate) enum GitInfoError {
Expand Down Expand Up @@ -80,24 +82,30 @@ impl Tags {
.find(|git_dir| git_dir.exists())
.ok_or_else(|| GitInfoError::MissingGitDir(path.to_path_buf()))?;

let git_refs_path =
git_refs(&git_dir).ok_or_else(|| GitInfoError::MissingRefs(git_dir.clone()))?;
let git_tags_path = git_refs(&git_dir)
.ok_or_else(|| GitInfoError::MissingRefs(git_dir.clone()))?
.join("tags");

let mut tags = BTreeMap::new();

// Map each tag to its commit.
let read_dir = match fs_err::read_dir(git_refs_path.join("tags")) {
Ok(read_dir) => read_dir,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
return Ok(Self(tags));
}
Err(err) => return Err(err.into()),
};
for entry in read_dir {
let entry = entry?;
for entry in WalkDir::new(&git_tags_path).contents_first(true) {
let entry = match entry {
Ok(entry) => entry,
Err(err) => {
warn!("Failed to read git tags: {err}");
continue;
}
};
let path = entry.path();
if let Some(tag) = path.file_name().and_then(|name| name.to_str()) {
let commit = fs_err::read_to_string(&path)?.trim().to_string();
let is_file = entry
.metadata()
.map_or(false, |metadata| metadata.is_file());

if !is_file {
continue;
}
if let Ok(Some(tag)) = path.strip_prefix(&git_tags_path).map(|name| name.to_str()) {
let commit = fs_err::read_to_string(path)?.trim().to_string();

// The commit should be 40 hexadecimal characters.
if commit.len() != 40 {
Expand Down

0 comments on commit 62ba062

Please sign in to comment.