mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
WIP: Add stateful status bubbling to worktree
This commit is contained in:
parent
4717ce1da3
commit
5e43dcaab8
@ -199,6 +199,24 @@ pub enum GitFileStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GitFileStatus {
|
impl GitFileStatus {
|
||||||
|
pub fn merge(
|
||||||
|
this: Option<GitFileStatus>,
|
||||||
|
other: Option<GitFileStatus>,
|
||||||
|
) -> Option<GitFileStatus> {
|
||||||
|
match (this, other) {
|
||||||
|
(Some(GitFileStatus::Conflict), _) | (_, Some(GitFileStatus::Conflict)) => {
|
||||||
|
Some(GitFileStatus::Conflict)
|
||||||
|
}
|
||||||
|
(Some(GitFileStatus::Modified), _) | (_, Some(GitFileStatus::Modified)) => {
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
}
|
||||||
|
(Some(GitFileStatus::Added), _) | (_, Some(GitFileStatus::Added)) => {
|
||||||
|
Some(GitFileStatus::Added)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_proto(git_status: Option<i32>) -> Option<GitFileStatus> {
|
pub fn from_proto(git_status: Option<i32>) -> Option<GitFileStatus> {
|
||||||
git_status.and_then(|status| {
|
git_status.and_then(|status| {
|
||||||
proto::GitStatus::from_i32(status).map(|status| match status {
|
proto::GitStatus::from_i32(status).map(|status| match status {
|
||||||
|
@ -1958,20 +1958,32 @@ impl LocalSnapshot {
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_statuses(&mut self, repo_ptr: &dyn GitRepository, work_directory: &RepositoryWorkDirectory) {
|
fn scan_statuses(
|
||||||
|
&mut self,
|
||||||
|
repo_ptr: &dyn GitRepository,
|
||||||
|
work_directory: &RepositoryWorkDirectory,
|
||||||
|
) {
|
||||||
let statuses = repo_ptr.statuses().unwrap_or_default();
|
let statuses = repo_ptr.statuses().unwrap_or_default();
|
||||||
|
let mut edits = vec![];
|
||||||
for (repo_path, status) in statuses.iter() {
|
for (repo_path, status) in statuses.iter() {
|
||||||
let Some(entry) = self.entry_for_path(&work_directory.0.join(repo_path)) else {
|
self.set_git_status(&work_directory.0.join(repo_path), Some(*status), &mut edits);
|
||||||
|
}
|
||||||
|
self.entries_by_path.edit(edits, &());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_git_status(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
status: Option<GitFileStatus>,
|
||||||
|
edits: &mut Vec<Edit<Entry>>,
|
||||||
|
) {
|
||||||
|
for path in path.ancestors() {
|
||||||
|
let Some(entry) = self.entry_for_path(path) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut entry = entry.clone();
|
let mut entry = entry.clone();
|
||||||
entry.git_status = Some(*status);
|
entry.git_status = GitFileStatus::merge(entry.git_status, status);
|
||||||
|
edits.push(Edit::Insert(entry))
|
||||||
// TODO statuses
|
|
||||||
// Bubble
|
|
||||||
|
|
||||||
self.entries_by_path.insert_or_replace(entry, &());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3161,7 +3173,6 @@ impl BackgroundScanner {
|
|||||||
entry.branch = branch.map(Into::into);
|
entry.branch = branch.map(Into::into);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
snapshot.scan_statuses(repo.deref(), &work_dir);
|
snapshot.scan_statuses(repo.deref(), &work_dir);
|
||||||
} else {
|
} else {
|
||||||
if snapshot
|
if snapshot
|
||||||
@ -3185,13 +3196,13 @@ impl BackgroundScanner {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
for mut entry in snapshot
|
let mut edits = vec![];
|
||||||
|
|
||||||
|
for path in snapshot
|
||||||
.descendent_entries(false, false, path)
|
.descendent_entries(false, false, path)
|
||||||
.cloned()
|
.map(|entry| &entry.path)
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.into_iter()
|
|
||||||
{
|
{
|
||||||
let Some(repo_path) = repo.work_directory.relativize(snapshot, &entry.path) else {
|
let Some(repo_path) = repo.work_directory.relativize(snapshot, &path) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3199,11 +3210,10 @@ impl BackgroundScanner {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
entry.git_status = Some(status);
|
snapshot.set_git_status(&path, Some(status), &mut edits);
|
||||||
snapshot.entries_by_path.insert_or_replace(entry, &());
|
|
||||||
// TODO statuses
|
|
||||||
// Bubble
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snapshot.entries_by_path.edit(edits, &());
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
@ -4995,7 +5005,6 @@ mod tests {
|
|||||||
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|
||||||
const A_TXT: &'static str = "a.txt";
|
const A_TXT: &'static str = "a.txt";
|
||||||
const B_TXT: &'static str = "b.txt";
|
const B_TXT: &'static str = "b.txt";
|
||||||
const E_TXT: &'static str = "c/d/e.txt";
|
const E_TXT: &'static str = "c/d/e.txt";
|
||||||
@ -5012,8 +5021,6 @@ mod tests {
|
|||||||
git_add(Path::new(DOTGITIGNORE), &repo);
|
git_add(Path::new(DOTGITIGNORE), &repo);
|
||||||
git_commit("Initial commit", &repo);
|
git_commit("Initial commit", &repo);
|
||||||
|
|
||||||
std::fs::write(work_dir.join(A_TXT), "aa").unwrap();
|
|
||||||
|
|
||||||
tree.flush_fs_events(cx).await;
|
tree.flush_fs_events(cx).await;
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
|
||||||
@ -5024,10 +5031,6 @@ mod tests {
|
|||||||
let (dir, _) = snapshot.repository_entries.iter().next().unwrap();
|
let (dir, _) = snapshot.repository_entries.iter().next().unwrap();
|
||||||
assert_eq!(dir.0.as_ref(), Path::new("project"));
|
assert_eq!(dir.0.as_ref(), Path::new("project"));
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
snapshot.status_for_file(project_path.join(A_TXT)),
|
|
||||||
Some(GitFileStatus::Modified)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
snapshot.status_for_file(project_path.join(B_TXT)),
|
snapshot.status_for_file(project_path.join(B_TXT)),
|
||||||
Some(GitFileStatus::Added)
|
Some(GitFileStatus::Added)
|
||||||
@ -5036,6 +5039,36 @@ mod tests {
|
|||||||
snapshot.status_for_file(project_path.join(F_TXT)),
|
snapshot.status_for_file(project_path.join(F_TXT)),
|
||||||
Some(GitFileStatus::Added)
|
Some(GitFileStatus::Added)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Check stateful bubbling works
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(project_path),
|
||||||
|
Some(GitFileStatus::Added)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(snapshot.status_for_file(""), Some(GitFileStatus::Added));
|
||||||
|
});
|
||||||
|
|
||||||
|
std::fs::write(work_dir.join(A_TXT), "aa").unwrap();
|
||||||
|
|
||||||
|
tree.flush_fs_events(cx).await;
|
||||||
|
deterministic.run_until_parked();
|
||||||
|
|
||||||
|
tree.read_with(cx, |tree, _cx| {
|
||||||
|
let snapshot = tree.snapshot();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(project_path.join(A_TXT)),
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check stateful bubbling works, modified overrules added
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(project_path),
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(snapshot.status_for_file(""), Some(GitFileStatus::Modified));
|
||||||
});
|
});
|
||||||
|
|
||||||
git_add(Path::new(A_TXT), &repo);
|
git_add(Path::new(A_TXT), &repo);
|
||||||
@ -5052,6 +5085,17 @@ mod tests {
|
|||||||
snapshot.status_for_file(project_path.join(F_TXT)),
|
snapshot.status_for_file(project_path.join(F_TXT)),
|
||||||
Some(GitFileStatus::Added)
|
Some(GitFileStatus::Added)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(snapshot.status_for_file(project_path.join(B_TXT)), None);
|
||||||
|
assert_eq!(snapshot.status_for_file(project_path.join(A_TXT)), None);
|
||||||
|
|
||||||
|
// Check bubbling
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(project_path),
|
||||||
|
Some(GitFileStatus::Added)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(snapshot.status_for_file(""), Some(GitFileStatus::Added));
|
||||||
});
|
});
|
||||||
|
|
||||||
git_reset(0, &repo);
|
git_reset(0, &repo);
|
||||||
@ -5075,6 +5119,23 @@ mod tests {
|
|||||||
snapshot.status_for_file(project_path.join(E_TXT)),
|
snapshot.status_for_file(project_path.join(E_TXT)),
|
||||||
Some(GitFileStatus::Modified)
|
Some(GitFileStatus::Modified)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Check status bubbling
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(project_path.join(Path::new(E_TXT).parent().unwrap())),
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(
|
||||||
|
project_path.join(Path::new(E_TXT).parent().unwrap().parent().unwrap())
|
||||||
|
),
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
snapshot.status_for_file(project_path),
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
snapshot.status_for_file(project_path.join(F_TXT)),
|
snapshot.status_for_file(project_path.join(F_TXT)),
|
||||||
Some(GitFileStatus::Added)
|
Some(GitFileStatus::Added)
|
||||||
@ -5132,7 +5193,11 @@ mod tests {
|
|||||||
let snapshot = tree.snapshot();
|
let snapshot = tree.snapshot();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
snapshot.status_for_file(Path::new(renamed_dir_name).join(RENAMED_FILE)),
|
snapshot.status_for_file(
|
||||||
|
project_path
|
||||||
|
.join(Path::new(renamed_dir_name))
|
||||||
|
.join(RENAMED_FILE)
|
||||||
|
),
|
||||||
Some(GitFileStatus::Added)
|
Some(GitFileStatus::Added)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user