Add git status to the file system abstraction

co-authored-by: petros <petros@zed.dev>
This commit is contained in:
Mikayla Maki 2023-05-09 08:36:43 -07:00 committed by Mikayla Maki
parent 6385e51957
commit 7169f5c760
No known key found for this signature in database
4 changed files with 94 additions and 27 deletions

View file

@ -13,6 +13,7 @@ gpui = { path = "../gpui" }
lsp = { path = "../lsp" }
rope = { path = "../rope" }
util = { path = "../util" }
sum_tree = { path = "../sum_tree" }
anyhow.workspace = true
async-trait.workspace = true
futures.workspace = true

View file

@ -1,9 +1,10 @@
use anyhow::Result;
use collections::HashMap;
use parking_lot::Mutex;
use sum_tree::TreeMap;
use std::{
path::{Component, Path, PathBuf},
sync::Arc,
sync::Arc, ffi::OsStr, os::unix::prelude::OsStrExt,
};
use util::ResultExt;
@ -16,6 +17,8 @@ pub trait GitRepository: Send {
fn load_index_text(&self, relative_file_path: &Path) -> Option<String>;
fn branch_name(&self) -> Option<String>;
fn statuses(&self) -> Option<TreeMap<RepoPath, GitStatus>>;
}
impl std::fmt::Debug for dyn GitRepository {
@ -61,6 +64,79 @@ impl GitRepository for LibGitRepository {
let branch = String::from_utf8_lossy(head.shorthand_bytes());
Some(branch.to_string())
}
fn statuses(&self) -> Option<TreeMap<RepoPath, GitStatus>> {
let statuses = self.statuses(None).log_err()?;
let mut map = TreeMap::default();
for status in statuses.iter() {
let path = RepoPath(PathBuf::from(OsStr::from_bytes(status.path_bytes())));
let status_data = status.status();
let status = if status_data.contains(git2::Status::CONFLICTED) {
GitStatus::Conflict
} else if status_data.intersects(git2::Status::INDEX_MODIFIED
| git2::Status::WT_MODIFIED
| git2::Status::INDEX_RENAMED
| git2::Status::WT_RENAMED) {
GitStatus::Modified
} else if status_data.intersects(git2::Status::INDEX_NEW | git2::Status::WT_NEW) {
GitStatus::Added
} else {
GitStatus::Untracked
};
map.insert(path, status)
}
Some(map)
}
}
#[derive(Debug, Clone, Default)]
pub enum GitStatus {
Added,
Modified,
Conflict,
#[default]
Untracked,
}
#[derive(Clone, Debug, Ord, Hash, PartialOrd, Eq, PartialEq)]
pub struct RepoPath(PathBuf);
impl From<&Path> for RepoPath {
fn from(value: &Path) -> Self {
RepoPath(value.to_path_buf())
}
}
impl From<PathBuf> for RepoPath {
fn from(value: PathBuf) -> Self {
RepoPath(value)
}
}
impl Default for RepoPath {
fn default() -> Self {
RepoPath(PathBuf::new())
}
}
impl AsRef<Path> for RepoPath {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
impl std::ops::Deref for RepoPath {
type Target = PathBuf;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Debug, Clone, Default)]
@ -93,6 +169,10 @@ impl GitRepository for FakeGitRepository {
let state = self.state.lock();
state.branch_name.clone()
}
fn statuses(&self) -> Option<TreeMap<RepoPath, GitStatus>>{
todo!()
}
}
fn check_path_to_repo_path_errors(relative_file_path: &Path) -> Result<()> {