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
|
@ -13,7 +13,8 @@ use client::{User, RECEIVE_TIMEOUT};
|
|||
use collections::{HashMap, HashSet};
|
||||
use fs::{FakeFs, Fs as _, RemoveOptions};
|
||||
use futures::{channel::mpsc, StreamExt as _};
|
||||
use git::repository::GitFileStatus;
|
||||
|
||||
use git::status::{FileStatus, StatusCode, TrackedStatus, UnmergedStatus, UnmergedStatusCode};
|
||||
use gpui::{
|
||||
px, size, AppContext, BackgroundExecutor, Model, Modifiers, MouseButton, MouseDownEvent,
|
||||
TestAppContext, UpdateGlobal,
|
||||
|
@ -2889,11 +2890,20 @@ async fn test_git_status_sync(
|
|||
const A_TXT: &str = "a.txt";
|
||||
const B_TXT: &str = "b.txt";
|
||||
|
||||
const A_STATUS_START: FileStatus = FileStatus::Tracked(TrackedStatus {
|
||||
index_status: StatusCode::Added,
|
||||
worktree_status: StatusCode::Modified,
|
||||
});
|
||||
const B_STATUS_START: FileStatus = FileStatus::Unmerged(UnmergedStatus {
|
||||
first_head: UnmergedStatusCode::Updated,
|
||||
second_head: UnmergedStatusCode::Deleted,
|
||||
});
|
||||
|
||||
client_a.fs().set_status_for_repo_via_git_operation(
|
||||
Path::new("/dir/.git"),
|
||||
&[
|
||||
(Path::new(A_TXT), GitFileStatus::Added),
|
||||
(Path::new(B_TXT), GitFileStatus::Added),
|
||||
(Path::new(A_TXT), A_STATUS_START),
|
||||
(Path::new(B_TXT), B_STATUS_START),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -2913,7 +2923,7 @@ async fn test_git_status_sync(
|
|||
#[track_caller]
|
||||
fn assert_status(
|
||||
file: &impl AsRef<Path>,
|
||||
status: Option<GitFileStatus>,
|
||||
status: Option<FileStatus>,
|
||||
project: &Project,
|
||||
cx: &AppContext,
|
||||
) {
|
||||
|
@ -2926,20 +2936,29 @@ async fn test_git_status_sync(
|
|||
}
|
||||
|
||||
project_local.read_with(cx_a, |project, cx| {
|
||||
assert_status(&Path::new(A_TXT), Some(GitFileStatus::Added), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(GitFileStatus::Added), project, cx);
|
||||
assert_status(&Path::new(A_TXT), Some(A_STATUS_START), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(B_STATUS_START), project, cx);
|
||||
});
|
||||
|
||||
project_remote.read_with(cx_b, |project, cx| {
|
||||
assert_status(&Path::new(A_TXT), Some(GitFileStatus::Added), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(GitFileStatus::Added), project, cx);
|
||||
assert_status(&Path::new(A_TXT), Some(A_STATUS_START), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(B_STATUS_START), project, cx);
|
||||
});
|
||||
|
||||
const A_STATUS_END: FileStatus = FileStatus::Tracked(TrackedStatus {
|
||||
index_status: StatusCode::Added,
|
||||
worktree_status: StatusCode::Unmodified,
|
||||
});
|
||||
const B_STATUS_END: FileStatus = FileStatus::Tracked(TrackedStatus {
|
||||
index_status: StatusCode::Deleted,
|
||||
worktree_status: StatusCode::Unmodified,
|
||||
});
|
||||
|
||||
client_a.fs().set_status_for_repo_via_working_copy_change(
|
||||
Path::new("/dir/.git"),
|
||||
&[
|
||||
(Path::new(A_TXT), GitFileStatus::Modified),
|
||||
(Path::new(B_TXT), GitFileStatus::Modified),
|
||||
(Path::new(A_TXT), A_STATUS_END),
|
||||
(Path::new(B_TXT), B_STATUS_END),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -2949,33 +2968,13 @@ async fn test_git_status_sync(
|
|||
// Smoke test status reading
|
||||
|
||||
project_local.read_with(cx_a, |project, cx| {
|
||||
assert_status(
|
||||
&Path::new(A_TXT),
|
||||
Some(GitFileStatus::Modified),
|
||||
project,
|
||||
cx,
|
||||
);
|
||||
assert_status(
|
||||
&Path::new(B_TXT),
|
||||
Some(GitFileStatus::Modified),
|
||||
project,
|
||||
cx,
|
||||
);
|
||||
assert_status(&Path::new(A_TXT), Some(A_STATUS_END), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(B_STATUS_END), project, cx);
|
||||
});
|
||||
|
||||
project_remote.read_with(cx_b, |project, cx| {
|
||||
assert_status(
|
||||
&Path::new(A_TXT),
|
||||
Some(GitFileStatus::Modified),
|
||||
project,
|
||||
cx,
|
||||
);
|
||||
assert_status(
|
||||
&Path::new(B_TXT),
|
||||
Some(GitFileStatus::Modified),
|
||||
project,
|
||||
cx,
|
||||
);
|
||||
assert_status(&Path::new(A_TXT), Some(A_STATUS_END), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(B_STATUS_END), project, cx);
|
||||
});
|
||||
|
||||
// And synchronization while joining
|
||||
|
@ -2983,18 +2982,8 @@ async fn test_git_status_sync(
|
|||
executor.run_until_parked();
|
||||
|
||||
project_remote_c.read_with(cx_c, |project, cx| {
|
||||
assert_status(
|
||||
&Path::new(A_TXT),
|
||||
Some(GitFileStatus::Modified),
|
||||
project,
|
||||
cx,
|
||||
);
|
||||
assert_status(
|
||||
&Path::new(B_TXT),
|
||||
Some(GitFileStatus::Modified),
|
||||
project,
|
||||
cx,
|
||||
);
|
||||
assert_status(&Path::new(A_TXT), Some(A_STATUS_END), project, cx);
|
||||
assert_status(&Path::new(B_TXT), Some(B_STATUS_END), project, cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue