diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 1925e84735a8020c7e1896f3cf2e7ee20ae3f712..aed08e8dc850622cff4dc96631199a039c78ac3f 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -1318,33 +1318,31 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { fn logic(repo: &git2::Repository, path: &RepoPath) -> Result> { - // This check is required because index.get_path() unwraps internally :( let mut index = repo.index()?; index.read(false)?; const STAGE_NORMAL: i32 = 0; - let path = path.as_std_path(); - // `RepoPath` contains a `RelPath` which normalizes `.` into an empty path - // `get_path` unwraps on empty paths though, so undo that normalization here - let path = if path.components().next().is_none() { - ".".as_ref() + // git2 unwraps internally on empty paths or `.` + if path.is_empty() { + bail!("empty path has no index text"); + } + let entry = index + .get_path(path.as_std_path(), STAGE_NORMAL) + .with_context(|| format!("looking up {path:?} in index"))?; + let oid = if entry.mode != GIT_MODE_SYMLINK { + entry.id } else { - path - }; - let oid = match index.get_path(path, STAGE_NORMAL) { - Some(entry) if entry.mode != GIT_MODE_SYMLINK => entry.id, - _ => return Ok(None), + return Ok(None); }; let content = repo.find_blob(oid)?.content().to_owned(); Ok(String::from_utf8(content).ok()) } - match logic(&repo.lock(), &path) { - Ok(value) => return value, - Err(err) => log::error!("Error loading index text: {:?}", err), - } - None + logic(&repo.lock(), &path) + .context("loading index text") + .log_err() + .flatten() }) .boxed() } @@ -1353,14 +1351,27 @@ impl GitRepository for RealGitRepository { let repo = self.repository.clone(); self.executor .spawn(async move { - let repo = repo.lock(); - let head = repo.head().ok()?.peel_to_tree().log_err()?; - let entry = head.get_path(path.as_std_path()).ok()?; - if entry.filemode() == i32::from(git2::FileMode::Link) { - return None; + fn logic(repo: &git2::Repository, path: &RepoPath) -> Result> { + let head = repo.head()?.peel_to_tree()?; + if path.is_empty() { + return Err(anyhow!("empty path has no committed text")); + } + // git2 unwraps internally on empty paths or `.` + let entry = head.get_path(path.as_std_path())?; + if entry.filemode() == i32::from(git2::FileMode::Link) { + bail!( + "symlink has no + committed text" + ); + } + let content = repo.find_blob(entry.id())?.content().to_owned(); + Ok(String::from_utf8(content).ok()) } - let content = repo.find_blob(entry.id()).log_err()?.content().to_owned(); - String::from_utf8(content).ok() + + logic(&repo.lock(), &path) + .context("loading committed text") + .log_err() + .flatten() }) .boxed() }