Worktree paths in git panel, take 2 (#26047)
Modified version of #25950. We still use worktree paths, but repo paths with a status that lie outside the worktree are not excluded; instead, we relativize them by adding `..`. This makes the list in the git panel match what you'd get from running `git status` (with the repo's worktree root as the working directory). - [x] Implement + test new unrelativization logic - [x] ~~When collecting repositories, dedup by .git abs path, so worktrees can share a repo at the project level~~ dedup repos at the repository selector layer, with repos coming from larger worktrees being preferred - [x] Open single-file worktree with diff when activating a path not in the worktree Release Notes: - N/A
This commit is contained in:
parent
330e799293
commit
1763dd714b
23 changed files with 724 additions and 184 deletions
|
@ -3,7 +3,10 @@ use gpui::{
|
|||
};
|
||||
use itertools::Itertools;
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use project::{git::Repository, Project};
|
||||
use project::{
|
||||
git::{GitStore, Repository},
|
||||
Project,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use ui::{prelude::*, ListItem, ListItemSpacing};
|
||||
|
||||
|
@ -17,12 +20,14 @@ impl RepositorySelector {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let git_store = project_handle.read(cx).git_store().clone();
|
||||
let repository_entries = git_store.update(cx, |git_store, cx| {
|
||||
filtered_repository_entries(git_store, cx)
|
||||
});
|
||||
let project = project_handle.read(cx);
|
||||
let git_store = project.git_store().clone();
|
||||
let all_repositories = git_store.read(cx).all_repositories();
|
||||
let filtered_repositories = all_repositories.clone();
|
||||
let filtered_repositories = repository_entries.clone();
|
||||
|
||||
let widest_item_ix = all_repositories.iter().position_max_by(|a, b| {
|
||||
let widest_item_ix = repository_entries.iter().position_max_by(|a, b| {
|
||||
a.read(cx)
|
||||
.display_name(project, cx)
|
||||
.len()
|
||||
|
@ -32,7 +37,7 @@ impl RepositorySelector {
|
|||
let delegate = RepositorySelectorDelegate {
|
||||
project: project_handle.downgrade(),
|
||||
repository_selector: cx.entity().downgrade(),
|
||||
repository_entries: all_repositories.clone(),
|
||||
repository_entries,
|
||||
filtered_repositories,
|
||||
selected_index: 0,
|
||||
};
|
||||
|
@ -47,6 +52,35 @@ impl RepositorySelector {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn filtered_repository_entries(
|
||||
git_store: &GitStore,
|
||||
cx: &App,
|
||||
) -> Vec<Entity<Repository>> {
|
||||
let mut repository_entries = git_store.all_repositories();
|
||||
repository_entries.sort_by_key(|repo| {
|
||||
let repo = repo.read(cx);
|
||||
(
|
||||
repo.dot_git_abs_path.clone(),
|
||||
repo.worktree_abs_path.clone(),
|
||||
)
|
||||
});
|
||||
// Remove any entry that comes from a single file worktree and represents a repository that is also represented by a non-single-file worktree.
|
||||
repository_entries
|
||||
.chunk_by(|a, b| a.read(cx).dot_git_abs_path == b.read(cx).dot_git_abs_path)
|
||||
.flat_map(|chunk| {
|
||||
let has_non_single_file_worktree = chunk
|
||||
.iter()
|
||||
.any(|repo| !repo.read(cx).is_from_single_file_worktree);
|
||||
chunk
|
||||
.iter()
|
||||
.filter(move |repo| {
|
||||
!repo.read(cx).is_from_single_file_worktree || !has_non_single_file_worktree
|
||||
})
|
||||
.cloned()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
impl EventEmitter<DismissEvent> for RepositorySelector {}
|
||||
|
||||
impl Focusable for RepositorySelector {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue