Represent git statuses more faithfully (#23082)
First, parse the output of `git status --porcelain=v1` into a representation that can handle the full "grammar" and doesn't lose information. Second, as part of pushing this throughout the codebase, expand the use of the existing `GitSummary` type to all the places where status propagation is in play (i.e., anywhere we're dealing with a mix of files and directories), and get rid of the previous `GitSummary -> GitFileStatus` conversion. - [x] Synchronize new representation over collab - [x] Update zed.proto - [x] Update DB models - [x] Update `GitSummary` and summarization for the new `FileStatus` - [x] Fix all tests - [x] worktree - [x] collab - [x] Clean up `FILE_*` constants - [x] New collab tests to exercise syncing of complex statuses - [x] Run it locally and make sure it looks good Release Notes: - N/A --------- Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
224f3d4746
commit
a41d72ee81
24 changed files with 1015 additions and 552 deletions
|
@ -9,10 +9,7 @@ use std::{
|
|||
use anyhow::{anyhow, Context as _};
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use feature_flags::FeatureFlagAppExt;
|
||||
use git::{
|
||||
diff::{BufferDiff, DiffHunk},
|
||||
repository::GitFileStatus,
|
||||
};
|
||||
use git::diff::{BufferDiff, DiffHunk};
|
||||
use gpui::{
|
||||
actions, AnyElement, AnyView, AppContext, EventEmitter, FocusHandle, FocusableView,
|
||||
InteractiveElement, Model, Render, Subscription, Task, View, WeakView,
|
||||
|
@ -54,7 +51,6 @@ struct ProjectDiffEditor {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct Changes {
|
||||
_status: GitFileStatus,
|
||||
buffer: Model<Buffer>,
|
||||
hunks: Vec<DiffHunk>,
|
||||
}
|
||||
|
@ -199,14 +195,13 @@ impl ProjectDiffEditor {
|
|||
.repositories()
|
||||
.iter()
|
||||
.flat_map(|entry| {
|
||||
entry.status().map(|git_entry| {
|
||||
(git_entry.combined_status(), entry.join(git_entry.repo_path))
|
||||
})
|
||||
entry
|
||||
.status()
|
||||
.map(|git_entry| entry.join(git_entry.repo_path))
|
||||
})
|
||||
.filter_map(|(status, path)| {
|
||||
.filter_map(|path| {
|
||||
let id = snapshot.entry_for_path(&path)?.id;
|
||||
Some((
|
||||
status,
|
||||
id,
|
||||
ProjectPath {
|
||||
worktree_id: snapshot.id(),
|
||||
|
@ -218,9 +213,9 @@ impl ProjectDiffEditor {
|
|||
Some(
|
||||
applicable_entries
|
||||
.into_iter()
|
||||
.map(|(status, entry_id, entry_path)| {
|
||||
.map(|(entry_id, entry_path)| {
|
||||
let open_task = project.open_path(entry_path.clone(), cx);
|
||||
(status, entry_id, entry_path, open_task)
|
||||
(entry_id, entry_path, open_task)
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
|
@ -234,15 +229,10 @@ impl ProjectDiffEditor {
|
|||
let mut new_entries = Vec::new();
|
||||
let mut buffers = HashMap::<
|
||||
ProjectEntryId,
|
||||
(
|
||||
GitFileStatus,
|
||||
text::BufferSnapshot,
|
||||
Model<Buffer>,
|
||||
BufferDiff,
|
||||
),
|
||||
(text::BufferSnapshot, Model<Buffer>, BufferDiff),
|
||||
>::default();
|
||||
let mut change_sets = Vec::new();
|
||||
for (status, entry_id, entry_path, open_task) in open_tasks {
|
||||
for (entry_id, entry_path, open_task) in open_tasks {
|
||||
let Some(buffer) = open_task
|
||||
.await
|
||||
.and_then(|(_, opened_model)| {
|
||||
|
@ -272,7 +262,6 @@ impl ProjectDiffEditor {
|
|||
buffers.insert(
|
||||
entry_id,
|
||||
(
|
||||
status,
|
||||
buffer.read(cx).text_snapshot(),
|
||||
buffer,
|
||||
change_set.read(cx).diff_to_buffer.clone(),
|
||||
|
@ -295,11 +284,10 @@ impl ProjectDiffEditor {
|
|||
.background_executor()
|
||||
.spawn(async move {
|
||||
let mut new_changes = HashMap::<ProjectEntryId, Changes>::default();
|
||||
for (entry_id, (status, buffer_snapshot, buffer, buffer_diff)) in buffers {
|
||||
for (entry_id, (buffer_snapshot, buffer, buffer_diff)) in buffers {
|
||||
new_changes.insert(
|
||||
entry_id,
|
||||
Changes {
|
||||
_status: status,
|
||||
buffer,
|
||||
hunks: buffer_diff
|
||||
.hunks_in_row_range(0..BufferRow::MAX, &buffer_snapshot)
|
||||
|
@ -1107,6 +1095,7 @@ impl Render for ProjectDiffEditor {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use git::status::{StatusCode, TrackedStatus};
|
||||
use gpui::{SemanticVersion, TestAppContext, VisualTestContext};
|
||||
use project::buffer_store::BufferChangeSet;
|
||||
use serde_json::json;
|
||||
|
@ -1224,7 +1213,14 @@ mod tests {
|
|||
});
|
||||
fs.set_status_for_repo_via_git_operation(
|
||||
Path::new("/root/.git"),
|
||||
&[(Path::new("file_a"), GitFileStatus::Modified)],
|
||||
&[(
|
||||
Path::new("file_a"),
|
||||
TrackedStatus {
|
||||
worktree_status: StatusCode::Modified,
|
||||
index_status: StatusCode::Unmodified,
|
||||
}
|
||||
.into(),
|
||||
)],
|
||||
);
|
||||
cx.executor()
|
||||
.advance_clock(UPDATE_DEBOUNCE + Duration::from_millis(100));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue