diff --git a/crates/collab/src/db/queries/projects.rs b/crates/collab/src/db/queries/projects.rs index c8651216434d404f7ab4a88fbb5fbb5f7d0aa3ee..51a0ef83323ec70675283d2fdec7ca1ad791b12d 100644 --- a/crates/collab/src/db/queries/projects.rs +++ b/crates/collab/src/db/queries/projects.rs @@ -1005,7 +1005,6 @@ impl Database { is_last_update: true, merge_message: db_repository_entry.merge_message, stash_entries: Vec::new(), - renamed_paths: Default::default(), }); } } diff --git a/crates/collab/src/db/queries/rooms.rs b/crates/collab/src/db/queries/rooms.rs index 151e4c442bd7d0a25053e35b94d9e2ad9817a6a3..f020b99b5f1030cfe9391498512258e6db249bac 100644 --- a/crates/collab/src/db/queries/rooms.rs +++ b/crates/collab/src/db/queries/rooms.rs @@ -796,7 +796,6 @@ impl Database { is_last_update: true, merge_message: db_repository.merge_message, stash_entries: Vec::new(), - renamed_paths: Default::default(), }); } } diff --git a/crates/fs/src/fake_git_repo.rs b/crates/fs/src/fake_git_repo.rs index de7c0561ebc9918a2686402fb9b62608566c7d9c..97cd13d185817453c369356bdc60cbc1517bf1e1 100644 --- a/crates/fs/src/fake_git_repo.rs +++ b/crates/fs/src/fake_git_repo.rs @@ -359,7 +359,6 @@ impl GitRepository for FakeGitRepository { entries.sort_by(|a, b| a.0.cmp(&b.0)); anyhow::Ok(GitStatus { entries: entries.into(), - renamed_paths: HashMap::default(), }) }); Task::ready(match result { diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 2eb37038cde2f4d0c4dc4903fdc06f86ab543827..2c9189962492daa75dba86e9e2ebd247ad85254e 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -2045,7 +2045,7 @@ fn git_status_args(path_prefixes: &[RepoPath]) -> Vec { OsString::from("status"), OsString::from("--porcelain=v1"), OsString::from("--untracked-files=all"), - OsString::from("--find-renames"), + OsString::from("--no-renames"), OsString::from("-z"), ]; args.extend( diff --git a/crates/git/src/status.rs b/crates/git/src/status.rs index 9b76fe75dd284c08c0f2e9b20116bc51dc4bc56c..2cf7cc7c1810620f1cf1aaea831fb337810c83d8 100644 --- a/crates/git/src/status.rs +++ b/crates/git/src/status.rs @@ -203,14 +203,6 @@ impl FileStatus { matches!(self, FileStatus::Untracked) } - pub fn is_renamed(self) -> bool { - let FileStatus::Tracked(tracked) = self else { - return false; - }; - tracked.index_status == StatusCode::Renamed - || tracked.worktree_status == StatusCode::Renamed - } - pub fn summary(self) -> GitSummary { match self { FileStatus::Ignored => GitSummary::UNCHANGED, @@ -438,79 +430,34 @@ impl std::ops::Sub for GitSummary { #[derive(Clone, Debug)] pub struct GitStatus { pub entries: Arc<[(RepoPath, FileStatus)]>, - pub renamed_paths: HashMap, } impl FromStr for GitStatus { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - let mut parts = s.split('\0').peekable(); - let mut entries = Vec::new(); - let mut renamed_paths = HashMap::default(); - - while let Some(entry) = parts.next() { - if entry.is_empty() { - continue; - } - - if !matches!(entry.get(2..3), Some(" ")) { - continue; - } - - let path_or_old_path = &entry[3..]; - - if path_or_old_path.ends_with('/') { - continue; - } - - let status = match entry.as_bytes()[0..2].try_into() { - Ok(bytes) => match FileStatus::from_bytes(bytes).log_err() { - Some(s) => s, - None => continue, - }, - Err(_) => continue, - }; - - let is_rename = matches!( - status, - FileStatus::Tracked(TrackedStatus { - index_status: StatusCode::Renamed | StatusCode::Copied, - .. - }) | FileStatus::Tracked(TrackedStatus { - worktree_status: StatusCode::Renamed | StatusCode::Copied, - .. - }) - ); - - let (old_path_str, new_path_str) = if is_rename { - let new_path = match parts.next() { - Some(new_path) if !new_path.is_empty() => new_path, - _ => continue, + let mut entries = s + .split('\0') + .filter_map(|entry| { + let sep = entry.get(2..3)?; + if sep != " " { + return None; }; - (path_or_old_path, new_path) - } else { - (path_or_old_path, path_or_old_path) - }; - - if new_path_str.ends_with('/') { - continue; - } - - let new_path = match RelPath::unix(new_path_str).log_err() { - Some(p) => RepoPath::from_rel_path(p), - None => continue, - }; - - if is_rename { - if let Some(old_path_rel) = RelPath::unix(old_path_str).log_err() { - let old_path_repo = RepoPath::from_rel_path(old_path_rel); - renamed_paths.insert(new_path.clone(), old_path_repo); + let path = &entry[3..]; + // The git status output includes untracked directories as well as untracked files. + // We do our own processing to compute the "summary" status of each directory, + // so just skip any directories in the output, since they'll otherwise interfere + // with our handling of nested repositories. + if path.ends_with('/') { + return None; } - } - - entries.push((new_path, status)); - } + let status = entry.as_bytes()[0..2].try_into().unwrap(); + let status = FileStatus::from_bytes(status).log_err()?; + // git-status outputs `/`-delimited repo paths, even on Windows. + let path = RepoPath::from_rel_path(RelPath::unix(path).log_err()?); + Some((path, status)) + }) + .collect::>(); entries.sort_unstable_by(|(a, _), (b, _)| a.cmp(b)); // When a file exists in HEAD, is deleted in the index, and exists again in the working copy, // git produces two lines for it, one reading `D ` (deleted in index, unmodified in working copy) @@ -534,7 +481,6 @@ impl FromStr for GitStatus { }); Ok(Self { entries: entries.into(), - renamed_paths, }) } } @@ -543,7 +489,6 @@ impl Default for GitStatus { fn default() -> Self { Self { entries: Arc::new([]), - renamed_paths: HashMap::default(), } } } diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 0691ba78560e38f5d3a297d033bd41459dff78c4..e2a4a26b320284fed727a7f7e60acf807c39abf0 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -3957,20 +3957,6 @@ impl GitPanel { let path_style = self.project.read(cx).path_style(cx); let display_name = entry.display_name(path_style); - let active_repo = self - .project - .read(cx) - .active_repository(cx) - .expect("active repository must be set"); - let repo = active_repo.read(cx); - let repo_snapshot = repo.snapshot(); - - let old_path = if entry.status.is_renamed() { - repo_snapshot.renamed_paths.get(&entry.repo_path) - } else { - None - }; - let selected = self.selected_entry == Some(ix); let marked = self.marked_entries.contains(&ix); let status_style = GitPanelSettings::get_global(cx).status_style; @@ -3979,16 +3965,15 @@ impl GitPanel { let has_conflict = status.is_conflicted(); let is_modified = status.is_modified(); let is_deleted = status.is_deleted(); - let is_renamed = status.is_renamed(); let label_color = if status_style == StatusStyle::LabelColor { if has_conflict { Color::VersionControlConflict + } else if is_modified { + Color::VersionControlModified } else if is_deleted { // We don't want a bunch of red labels in the list Color::Disabled - } else if is_renamed || is_modified { - Color::VersionControlModified } else { Color::VersionControlAdded } @@ -4008,6 +3993,12 @@ impl GitPanel { let checkbox_id: ElementId = ElementId::Name(format!("entry_{}_{}_checkbox", display_name, ix).into()); + let active_repo = self + .project + .read(cx) + .active_repository(cx) + .expect("active repository must be set"); + let repo = active_repo.read(cx); // Checking for current staged/unstaged file status is a chained operation: // 1. first, we check for any pending operation recorded in repository // 2. if there are no pending ops either running or finished, we then ask the repository @@ -4162,32 +4153,23 @@ impl GitPanel { .items_center() .flex_1() // .overflow_hidden() - .when_some(old_path.as_ref(), |this, old_path| { - let new_display = old_path.display(path_style).to_string(); - let old_display = entry.repo_path.display(path_style).to_string(); - this.child(self.entry_label(old_display, Color::Muted).strikethrough()) - .child(self.entry_label(" → ", Color::Muted)) - .child(self.entry_label(new_display, label_color)) - }) - .when(old_path.is_none(), |this| { - this.when_some(entry.parent_dir(path_style), |this, parent| { - if !parent.is_empty() { - this.child( - self.entry_label( - format!("{parent}{}", path_style.separator()), - path_color, - ) - .when(status.is_deleted(), |this| this.strikethrough()), + .when_some(entry.parent_dir(path_style), |this, parent| { + if !parent.is_empty() { + this.child( + self.entry_label( + format!("{parent}{}", path_style.separator()), + path_color, ) - } else { - this - } - }) - .child( - self.entry_label(display_name, label_color) .when(status.is_deleted(), |this| this.strikethrough()), - ) - }), + ) + } else { + this + } + }) + .child( + self.entry_label(display_name, label_color) + .when(status.is_deleted(), |this| this.strikethrough()), + ), ) .into_any_element() } diff --git a/crates/git_ui/src/git_ui.rs b/crates/git_ui/src/git_ui.rs index 3a664b484a8ec6d31bd243917888d864280b281d..b4e833f7af72cf7843d3797b51ea349b24c7adc5 100644 --- a/crates/git_ui/src/git_ui.rs +++ b/crates/git_ui/src/git_ui.rs @@ -708,11 +708,6 @@ impl RenderOnce for GitStatusIcon { IconName::SquareMinus, cx.theme().colors().version_control_deleted, ) - } else if status.is_renamed() { - ( - IconName::ArrowRight, - cx.theme().colors().version_control_modified, - ) } else if status.is_modified() { ( IconName::SquareDot, diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index 94af9859df1156d7a10286a843a31e8351fe050c..4cac71c6ae3e2eb3f3615821443db7c82e01d810 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -256,7 +256,6 @@ pub struct RepositorySnapshot { pub id: RepositoryId, pub statuses_by_path: SumTree, pub pending_ops_by_path: SumTree, - pub renamed_paths: HashMap, pub work_directory_abs_path: Arc, pub path_style: PathStyle, pub branch: Option, @@ -3064,7 +3063,6 @@ impl RepositorySnapshot { id, statuses_by_path: Default::default(), pending_ops_by_path: Default::default(), - renamed_paths: HashMap::default(), work_directory_abs_path, branch: None, head_commit: None, @@ -3106,11 +3104,6 @@ impl RepositorySnapshot { .iter() .map(stash_to_proto) .collect(), - renamed_paths: self - .renamed_paths - .iter() - .map(|(new_path, old_path)| (new_path.to_proto(), old_path.to_proto())) - .collect(), } } @@ -3180,11 +3173,6 @@ impl RepositorySnapshot { .iter() .map(stash_to_proto) .collect(), - renamed_paths: self - .renamed_paths - .iter() - .map(|(new_path, old_path)| (new_path.to_proto(), old_path.to_proto())) - .collect(), } } @@ -4980,17 +4968,6 @@ impl Repository { } self.snapshot.stash_entries = new_stash_entries; - self.snapshot.renamed_paths = update - .renamed_paths - .into_iter() - .filter_map(|(new_path_str, old_path_str)| { - Some(( - RepoPath::from_proto(&new_path_str).log_err()?, - RepoPath::from_proto(&old_path_str).log_err()?, - )) - }) - .collect(); - let edits = update .removed_statuses .into_iter() @@ -5766,7 +5743,6 @@ async fn compute_snapshot( id, statuses_by_path, pending_ops_by_path, - renamed_paths: statuses.renamed_paths, work_directory_abs_path, path_style: prev_snapshot.path_style, scan_id: prev_snapshot.scan_id + 1, diff --git a/crates/proto/proto/git.proto b/crates/proto/proto/git.proto index 8ed17864ec0c0403a4bb71f918d21b44a9b6cb13..efbd7f616f9e75c4e0409f4dc73c67f9eb1836e0 100644 --- a/crates/proto/proto/git.proto +++ b/crates/proto/proto/git.proto @@ -124,7 +124,6 @@ message UpdateRepository { optional GitCommitDetails head_commit_details = 11; optional string merge_message = 12; repeated StashEntry stash_entries = 13; - map renamed_paths = 14; } message RemoveRepository {