git: Fix panic in git2 due to empty repo paths (#42304)

Fixes ZED-1VR

Release Notes:

- Fixed sporadic panic in git features
This commit is contained in:
Lukas Wirth
2025-11-10 09:27:51 +00:00
committed by GitHub
parent 359160c8b1
commit 0149de4b54
13 changed files with 90 additions and 84 deletions
+18 -13
View File
@@ -227,7 +227,7 @@ impl sum_tree::Item for StatusEntry {
fn summary(&self, _: <Self::Summary as sum_tree::Summary>::Context<'_>) -> Self::Summary {
PathSummary {
max_path: self.repo_path.0.clone(),
max_path: self.repo_path.as_ref().clone(),
item_summary: self.status.summary(),
}
}
@@ -237,7 +237,7 @@ impl sum_tree::KeyedItem for StatusEntry {
type Key = PathKey;
fn key(&self) -> Self::Key {
PathKey(self.repo_path.0.clone())
PathKey(self.repo_path.as_ref().clone())
}
}
@@ -990,7 +990,7 @@ impl GitStore {
RepositoryState::Local { backend, .. } => backend
.blame(repo_path.clone(), content)
.await
.with_context(|| format!("Failed to blame {:?}", repo_path.0))
.with_context(|| format!("Failed to blame {:?}", repo_path.as_ref()))
.map(Some),
RepositoryState::Remote { project_id, client } => {
let response = client
@@ -2376,7 +2376,7 @@ impl GitStore {
.entries
.into_iter()
.map(|(path, status)| proto::TreeDiffStatus {
path: path.0.to_proto(),
path: path.as_ref().to_proto(),
status: match status {
TreeDiffStatus::Added {} => proto::tree_diff_status::Status::Added.into(),
TreeDiffStatus::Modified { .. } => {
@@ -3152,13 +3152,13 @@ impl RepositorySnapshot {
pub fn status_for_path(&self, path: &RepoPath) -> Option<StatusEntry> {
self.statuses_by_path
.get(&PathKey(path.0.clone()), ())
.get(&PathKey(path.as_ref().clone()), ())
.cloned()
}
pub fn pending_ops_for_path(&self, path: &RepoPath) -> Option<PendingOps> {
self.pending_ops_by_path
.get(&PathKey(path.0.clone()), ())
.get(&PathKey(path.as_ref().clone()), ())
.cloned()
}
@@ -4727,7 +4727,9 @@ impl Repository {
}
};
Some((
RepoPath(RelPath::from_proto(&entry.path).log_err()?),
RepoPath::from_rel_path(
&RelPath::from_proto(&entry.path).log_err()?,
),
status,
))
})
@@ -5289,7 +5291,8 @@ impl Repository {
let mut cursor = prev_statuses.cursor::<PathProgress>(());
for path in changed_paths.into_iter() {
if cursor.seek_forward(&PathTarget::Path(&path), Bias::Left) {
changed_path_statuses.push(Edit::Remove(PathKey(path.0)));
changed_path_statuses
.push(Edit::Remove(PathKey(path.as_ref().clone())));
}
}
changed_path_statuses
@@ -5435,10 +5438,8 @@ fn get_permalink_in_rust_registry_src(
remote,
BuildPermalinkParams::new(
&cargo_vcs_info.git.sha1,
&RepoPath(
RelPath::new(&path, PathStyle::local())
.context("invalid path")?
.into_arc(),
&RepoPath::from_rel_path(
&RelPath::new(&path, PathStyle::local()).context("invalid path")?,
),
Some(selection),
),
@@ -5640,7 +5641,11 @@ async fn compute_snapshot(
let mut events = Vec::new();
let branches = backend.branches().await?;
let branch = branches.into_iter().find(|branch| branch.is_head);
let statuses = backend.status(&[RelPath::empty().into()]).await?;
let statuses = backend
.status(&[RepoPath::from_rel_path(
&RelPath::new(".".as_ref(), PathStyle::local()).unwrap(),
)])
.await?;
let stash_entries = backend.stash_entries().await?;
let statuses_by_path = SumTree::from_iter(
statuses
+2 -2
View File
@@ -264,7 +264,7 @@ mod tests {
use super::*;
use fs::FakeFs;
use git::{
repository::repo_path,
repository::{RepoPath, repo_path},
status::{UnmergedStatus, UnmergedStatusCode},
};
use gpui::{BackgroundExecutor, TestAppContext};
@@ -617,7 +617,7 @@ mod tests {
cx.run_until_parked();
fs.with_git_state(path!("/project/.git").as_ref(), true, |state| {
state.unmerged_paths.insert(
rel_path("a.txt").into(),
RepoPath::from_rel_path(rel_path("a.txt")),
UnmergedStatus {
first_head: UnmergedStatusCode::Updated,
second_head: UnmergedStatusCode::Updated,
+2 -2
View File
@@ -46,7 +46,7 @@ impl Item for PendingOps {
fn summary(&self, _cx: ()) -> Self::Summary {
PathSummary {
max_path: self.repo_path.0.clone(),
max_path: self.repo_path.as_ref().clone(),
item_summary: PendingOpsSummary {
staged_count: self.staged() as usize,
staging_count: self.staging() as usize,
@@ -73,7 +73,7 @@ impl KeyedItem for PendingOps {
type Key = PathKey;
fn key(&self) -> Self::Key {
PathKey(self.repo_path.0.clone())
PathKey(self.repo_path.as_ref().clone())
}
}
+11 -15
View File
@@ -7937,7 +7937,7 @@ async fn test_staging_random_hunks(
log::info!(
"index text:\n{}",
repo.load_index_text(rel_path("file.txt").into())
repo.load_index_text(RepoPath::from_rel_path(rel_path("file.txt")))
.await
.unwrap()
);
@@ -8523,7 +8523,7 @@ async fn test_repository_pending_ops_staging(
assert_eq!(
pending_ops_all
.lock()
.get(&worktree::PathKey(repo_path("a.txt").0), ())
.get(&worktree::PathKey(repo_path("a.txt").as_ref().clone()), ())
.unwrap()
.ops,
vec![
@@ -8644,7 +8644,7 @@ async fn test_repository_pending_ops_long_running_staging(
assert_eq!(
pending_ops_all
.lock()
.get(&worktree::PathKey(repo_path("a.txt").0), ())
.get(&worktree::PathKey(repo_path("a.txt").as_ref().clone()), ())
.unwrap()
.ops,
vec![
@@ -8752,7 +8752,7 @@ async fn test_repository_pending_ops_stage_all(
assert_eq!(
pending_ops_all
.lock()
.get(&worktree::PathKey(repo_path("a.txt").0), ())
.get(&worktree::PathKey(repo_path("a.txt").as_ref().clone()), ())
.unwrap()
.ops,
vec![
@@ -8771,7 +8771,7 @@ async fn test_repository_pending_ops_stage_all(
assert_eq!(
pending_ops_all
.lock()
.get(&worktree::PathKey(repo_path("b.txt").0), ())
.get(&worktree::PathKey(repo_path("b.txt").as_ref().clone()), ())
.unwrap()
.ops,
vec![
@@ -9309,11 +9309,9 @@ async fn test_file_status(cx: &mut gpui::TestAppContext) {
repository.read_with(cx, |repository, _cx| {
assert_eq!(
repository
.status_for_path(
&rel_path(renamed_dir_name)
.join(rel_path(RENAMED_FILE))
.into()
)
.status_for_path(&RepoPath::from_rel_path(
&rel_path(renamed_dir_name).join(rel_path(RENAMED_FILE))
))
.unwrap()
.status,
FileStatus::Untracked,
@@ -9337,11 +9335,9 @@ async fn test_file_status(cx: &mut gpui::TestAppContext) {
repository.read_with(cx, |repository, _cx| {
assert_eq!(
repository
.status_for_path(
&rel_path(renamed_dir_name)
.join(rel_path(RENAMED_FILE))
.into()
)
.status_for_path(&RepoPath::from_rel_path(
&rel_path(renamed_dir_name).join(rel_path(RENAMED_FILE))
))
.unwrap()
.status,
FileStatus::Untracked,