Detailed changes
@@ -6829,6 +6829,32 @@ pub fn worktrees_directory_for_repo(
Ok(resolved)
}
+/// Returns a short name for a linked worktree suitable for UI display
+///
+/// Uses the main worktree path to come up with a short name that disambiguates
+/// the linked worktree from the main worktree.
+pub fn linked_worktree_short_name(
+ main_worktree_path: &Path,
+ linked_worktree_path: &Path,
+) -> Option<SharedString> {
+ if main_worktree_path == linked_worktree_path {
+ return None;
+ }
+
+ let project_name = main_worktree_path.file_name()?.to_str()?;
+ let directory_name = linked_worktree_path.file_name()?.to_str()?;
+ let name = if directory_name != project_name {
+ directory_name.to_string()
+ } else {
+ linked_worktree_path
+ .parent()?
+ .file_name()?
+ .to_str()?
+ .to_string()
+ };
+ Some(name.into())
+}
+
fn get_permalink_in_rust_registry_src(
provider_registry: Arc<GitHostingProviderRegistry>,
path: PathBuf,
@@ -47,7 +47,7 @@ pub use agent_server_store::{AgentId, AgentServerStore, AgentServersUpdated, Ext
pub use git_store::{
ConflictRegion, ConflictSet, ConflictSetSnapshot, ConflictSetUpdate,
git_traversal::{ChildEntriesGitIter, GitEntry, GitEntryRef, GitTraversal},
- worktrees_directory_for_repo,
+ linked_worktree_short_name, worktrees_directory_for_repo,
};
pub use manifest_tree::ManifestTree;
pub use project_search::{Search, SearchResults};
@@ -1539,7 +1539,7 @@ mod trust_tests {
mod resolve_worktree_tests {
use fs::FakeFs;
use gpui::TestAppContext;
- use project::git_store::resolve_git_worktree_to_main_repo;
+ use project::{git_store::resolve_git_worktree_to_main_repo, linked_worktree_short_name};
use serde_json::json;
use std::path::{Path, PathBuf};
@@ -1616,4 +1616,32 @@ mod resolve_worktree_tests {
resolve_git_worktree_to_main_repo(fs.as_ref(), Path::new("/does-not-exist")).await;
assert_eq!(result, None);
}
+
+ #[test]
+ fn test_linked_worktree_short_name() {
+ let examples = [
+ (
+ "/home/bob/zed",
+ "/home/bob/worktrees/olivetti/zed",
+ Some("olivetti".into()),
+ ),
+ ("/home/bob/zed", "/home/bob/zed2", Some("zed2".into())),
+ (
+ "/home/bob/zed",
+ "/home/bob/worktrees/zed/selectric",
+ Some("selectric".into()),
+ ),
+ ("/home/bob/zed", "/home/bob/zed", None),
+ ];
+ for (main_worktree_path, linked_worktree_path, expected) in examples {
+ let short_name = linked_worktree_short_name(
+ Path::new(main_worktree_path),
+ Path::new(linked_worktree_path),
+ );
+ assert_eq!(
+ short_name, expected,
+ "short name for {linked_worktree_path:?}, linked worktree of {main_worktree_path:?}, should be {expected:?}"
+ );
+ }
+ }
}
@@ -16,7 +16,7 @@ use gpui::{
use menu::{
Cancel, Confirm, SelectChild, SelectFirst, SelectLast, SelectNext, SelectParent, SelectPrevious,
};
-use project::{AgentId, Event as ProjectEvent};
+use project::{AgentId, Event as ProjectEvent, linked_worktree_short_name};
use recent_projects::RecentProjects;
use ui::utils::platform_title_bar_height;
@@ -780,16 +780,16 @@ impl Sidebar {
if snapshot.work_directory_abs_path != snapshot.original_repo_abs_path {
continue;
}
+
+ let main_worktree_path = snapshot.original_repo_abs_path.clone();
+
for git_worktree in snapshot.linked_worktrees() {
- let name = git_worktree
- .path
- .file_name()
- .unwrap_or_default()
- .to_string_lossy()
- .to_string();
+ let worktree_name =
+ linked_worktree_short_name(&main_worktree_path, &git_worktree.path)
+ .unwrap_or_default();
linked_worktree_queries.push((
PathList::new(std::slice::from_ref(&git_worktree.path)),
- name.into(),
+ worktree_name,
Arc::from(git_worktree.path.as_path()),
));
}
@@ -14,6 +14,7 @@ pub use platform_title_bar::{
self, DraggedWindowTab, MergeAllWindows, MoveTabToNewWindow, PlatformTitleBar,
ShowNextWindowTab, ShowPreviousWindowTab,
};
+use project::linked_worktree_short_name;
#[cfg(not(target_os = "macos"))]
use crate::application_menu::{
@@ -173,21 +174,19 @@ impl Render for TitleBar {
let mut repository = None;
let mut linked_worktree_name = None;
if let Some(worktree) = self.effective_active_worktree(cx) {
+ repository = self.get_repository_for_worktree(&worktree, cx);
+ let worktree = worktree.read(cx);
project_name = worktree
- .read(cx)
.root_name()
.file_name()
.map(|name| SharedString::from(name.to_string()));
- repository = self.get_repository_for_worktree(&worktree, cx);
linked_worktree_name = repository.as_ref().and_then(|repo| {
- let path = repo.read(cx).linked_worktree_path()?;
- let directory_name = path.file_name()?.to_str()?;
- let unique_worktree_name = if directory_name != project_name.as_ref()?.as_str() {
- directory_name.to_string()
- } else {
- path.parent()?.file_name()?.to_str()?.to_string()
- };
- Some(SharedString::from(unique_worktree_name))
+ let repo = repo.read(cx);
+ linked_worktree_short_name(
+ repo.original_repo_abs_path.as_ref(),
+ repo.work_directory_abs_path.as_ref(),
+ )
+ .filter(|name| Some(name) != project_name.as_ref())
});
}