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
|
@ -8,8 +8,7 @@ use anyhow::{Context as _, Result};
|
|||
use db::kvp::KEY_VALUE_STORE;
|
||||
use editor::scroll::ScrollbarAutoHide;
|
||||
use editor::{Editor, EditorSettings, ShowScrollbar};
|
||||
use git::repository::{GitFileStatus, RepoPath};
|
||||
use git::status::GitStatusPair;
|
||||
use git::{repository::RepoPath, status::FileStatus};
|
||||
use gpui::*;
|
||||
use language::Buffer;
|
||||
use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev};
|
||||
|
@ -72,7 +71,7 @@ pub struct GitListEntry {
|
|||
depth: usize,
|
||||
display_name: String,
|
||||
repo_path: RepoPath,
|
||||
status: GitStatusPair,
|
||||
status: FileStatus,
|
||||
is_staged: Option<bool>,
|
||||
}
|
||||
|
||||
|
@ -665,7 +664,7 @@ impl GitPanel {
|
|||
.skip(range.start)
|
||||
.take(range.end - range.start)
|
||||
{
|
||||
let status = entry.status.clone();
|
||||
let status = entry.status;
|
||||
let filename = entry
|
||||
.repo_path
|
||||
.file_name()
|
||||
|
@ -1072,22 +1071,23 @@ impl GitPanel {
|
|||
let repo_path = entry_details.repo_path.clone();
|
||||
let selected = self.selected_entry == Some(ix);
|
||||
let status_style = GitPanelSettings::get_global(cx).status_style;
|
||||
// TODO revisit, maybe use a different status here?
|
||||
let status = entry_details.status.combined();
|
||||
let status = entry_details.status;
|
||||
|
||||
let mut label_color = cx.theme().colors().text;
|
||||
if status_style == StatusStyle::LabelColor {
|
||||
label_color = match status {
|
||||
GitFileStatus::Added => cx.theme().status().created,
|
||||
GitFileStatus::Modified => cx.theme().status().modified,
|
||||
GitFileStatus::Conflict => cx.theme().status().conflict,
|
||||
GitFileStatus::Deleted => cx.theme().colors().text_disabled,
|
||||
// TODO: Should we even have this here?
|
||||
GitFileStatus::Untracked => cx.theme().colors().text_placeholder,
|
||||
label_color = if status.is_conflicted() {
|
||||
cx.theme().status().conflict
|
||||
} else if status.is_modified() {
|
||||
cx.theme().status().modified
|
||||
} else if status.is_deleted() {
|
||||
cx.theme().colors().text_disabled
|
||||
} else {
|
||||
cx.theme().status().created
|
||||
}
|
||||
}
|
||||
|
||||
let path_color = matches!(status, GitFileStatus::Deleted)
|
||||
let path_color = status
|
||||
.is_deleted()
|
||||
.then_some(cx.theme().colors().text_disabled)
|
||||
.unwrap_or(cx.theme().colors().text_muted);
|
||||
|
||||
|
@ -1175,7 +1175,7 @@ impl GitPanel {
|
|||
.child(
|
||||
h_flex()
|
||||
.text_color(label_color)
|
||||
.when(status == GitFileStatus::Deleted, |this| this.line_through())
|
||||
.when(status.is_deleted(), |this| this.line_through())
|
||||
.when_some(repo_path.parent(), |this, parent| {
|
||||
let parent_str = parent.to_string_lossy();
|
||||
if !parent_str.is_empty() {
|
||||
|
|
|
@ -2,7 +2,8 @@ use ::settings::Settings;
|
|||
use collections::HashMap;
|
||||
use futures::channel::mpsc;
|
||||
use futures::StreamExt as _;
|
||||
use git::repository::{GitFileStatus, GitRepository, RepoPath};
|
||||
use git::repository::{GitRepository, RepoPath};
|
||||
use git::status::FileStatus;
|
||||
use git_panel_settings::GitPanelSettings;
|
||||
use gpui::{actions, AppContext, Hsla, Model};
|
||||
use project::{Project, WorktreeId};
|
||||
|
@ -223,17 +224,15 @@ const REMOVED_COLOR: Hsla = Hsla {
|
|||
};
|
||||
|
||||
// TODO: Add updated status colors to theme
|
||||
pub fn git_status_icon(status: GitFileStatus) -> impl IntoElement {
|
||||
match status {
|
||||
GitFileStatus::Added | GitFileStatus::Untracked => {
|
||||
Icon::new(IconName::SquarePlus).color(Color::Custom(ADDED_COLOR))
|
||||
}
|
||||
GitFileStatus::Modified => {
|
||||
Icon::new(IconName::SquareDot).color(Color::Custom(MODIFIED_COLOR))
|
||||
}
|
||||
GitFileStatus::Conflict => Icon::new(IconName::Warning).color(Color::Custom(REMOVED_COLOR)),
|
||||
GitFileStatus::Deleted => {
|
||||
Icon::new(IconName::SquareMinus).color(Color::Custom(REMOVED_COLOR))
|
||||
}
|
||||
}
|
||||
pub fn git_status_icon(status: FileStatus) -> impl IntoElement {
|
||||
let (icon_name, color) = if status.is_conflicted() {
|
||||
(IconName::Warning, REMOVED_COLOR)
|
||||
} else if status.is_deleted() {
|
||||
(IconName::SquareMinus, REMOVED_COLOR)
|
||||
} else if status.is_modified() {
|
||||
(IconName::SquareDot, MODIFIED_COLOR)
|
||||
} else {
|
||||
(IconName::SquarePlus, ADDED_COLOR)
|
||||
};
|
||||
Icon::new(icon_name).color(Color::Custom(color))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue