mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-02 07:04:33 +00:00
Only archive worktrees that Zed created (#53991)
When archiving a thread, we now check whether the linked worktree lives inside the Zed-managed worktrees directory (configured via `git.worktree_directory`). If it doesn't — meaning the user created it themselves outside of Zed — we skip both the directory deletion and the `git worktree remove`, leaving it untouched. Previously, archiving a thread would delete *any* linked worktree associated with the thread's folder paths, even ones the user had created manually via `git worktree add`. Release Notes: - Fixed archiving an agent thread deleting linked git worktrees the user created outside of Zed's managed worktrees directory.
This commit is contained in:
parent
bf25cb1835
commit
e2780f6fbd
2 changed files with 257 additions and 36 deletions
|
|
@ -67,6 +67,16 @@ fn archived_worktree_ref_name(id: i64) -> String {
|
|||
format!("refs/archived-worktrees/{}", id)
|
||||
}
|
||||
|
||||
/// Resolves the Zed-managed worktrees base directory for a given repo.
|
||||
///
|
||||
/// This intentionally reads the *global* `git.worktree_directory` setting
|
||||
/// rather than any project-local override, because Zed always uses the
|
||||
/// global value when creating worktrees and the archive check must match.
|
||||
fn worktrees_base_for_repo(main_repo_path: &Path, cx: &App) -> Option<PathBuf> {
|
||||
let setting = &ProjectSettings::get_global(cx).git.worktree_directory;
|
||||
worktrees_directory_for_repo(main_repo_path, setting).log_err()
|
||||
}
|
||||
|
||||
/// Builds a [`RootPlan`] for archiving the git worktree at `path`.
|
||||
///
|
||||
/// This is a synchronous planning step that must run *before* any workspace
|
||||
|
|
@ -134,6 +144,15 @@ pub fn build_root_plan(
|
|||
// Main worktrees must be left alone — git refuses to remove them.
|
||||
let (linked_snapshot, repo) = linked_repo?;
|
||||
let main_repo_path = linked_snapshot.original_repo_abs_path.to_path_buf();
|
||||
|
||||
// Only archive worktrees that live inside the Zed-managed worktrees
|
||||
// directory (configured via `git.worktree_directory`). Worktrees the
|
||||
// user created outside that directory should be left untouched.
|
||||
let worktrees_base = worktrees_base_for_repo(&main_repo_path, cx)?;
|
||||
if !path.starts_with(&worktrees_base) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let branch_name = linked_snapshot
|
||||
.branch
|
||||
.as_ref()
|
||||
|
|
@ -246,10 +265,7 @@ async fn remove_empty_parent_dirs_up_to_worktrees_base(
|
|||
main_repo_path: PathBuf,
|
||||
cx: &mut AsyncApp,
|
||||
) {
|
||||
let worktrees_base = cx.update(|cx| {
|
||||
let setting = &ProjectSettings::get_global(cx).git.worktree_directory;
|
||||
worktrees_directory_for_repo(&main_repo_path, setting).log_err()
|
||||
});
|
||||
let worktrees_base = cx.update(|cx| worktrees_base_for_repo(&main_repo_path, cx));
|
||||
|
||||
if let Some(worktrees_base) = worktrees_base {
|
||||
cx.background_executor()
|
||||
|
|
@ -814,7 +830,7 @@ mod tests {
|
|||
use super::*;
|
||||
use fs::{FakeFs, Fs as _};
|
||||
use git::repository::Worktree as GitWorktree;
|
||||
use gpui::TestAppContext;
|
||||
use gpui::{BorrowAppContext, TestAppContext};
|
||||
use project::Project;
|
||||
use serde_json::json;
|
||||
use settings::SettingsStore;
|
||||
|
|
@ -997,7 +1013,7 @@ mod tests {
|
|||
Path::new("/project/.git"),
|
||||
true,
|
||||
GitWorktree {
|
||||
path: PathBuf::from("/linked-worktree"),
|
||||
path: PathBuf::from("/worktrees/project/feature/project"),
|
||||
ref_name: Some("refs/heads/feature".into()),
|
||||
sha: "abc123".into(),
|
||||
is_main: false,
|
||||
|
|
@ -1008,7 +1024,10 @@ mod tests {
|
|||
|
||||
let project = Project::test(
|
||||
fs.clone(),
|
||||
[Path::new("/project"), Path::new("/linked-worktree")],
|
||||
[
|
||||
Path::new("/project"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
|
@ -1027,7 +1046,7 @@ mod tests {
|
|||
workspace.read_with(cx, |_workspace, cx| {
|
||||
// The linked worktree SHOULD produce a root plan.
|
||||
let plan = build_root_plan(
|
||||
Path::new("/linked-worktree"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
std::slice::from_ref(&workspace),
|
||||
cx,
|
||||
);
|
||||
|
|
@ -1036,7 +1055,10 @@ mod tests {
|
|||
"build_root_plan should return Some for a linked worktree",
|
||||
);
|
||||
let plan = plan.unwrap();
|
||||
assert_eq!(plan.root_path, PathBuf::from("/linked-worktree"));
|
||||
assert_eq!(
|
||||
plan.root_path,
|
||||
PathBuf::from("/worktrees/project/feature/project")
|
||||
);
|
||||
assert_eq!(plan.main_repo_path, PathBuf::from("/project"));
|
||||
|
||||
// The main worktree should still return None.
|
||||
|
|
@ -1050,6 +1072,176 @@ mod tests {
|
|||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_build_root_plan_returns_none_for_external_linked_worktree(
|
||||
cx: &mut TestAppContext,
|
||||
) {
|
||||
init_test(cx);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/project",
|
||||
json!({
|
||||
".git": {},
|
||||
"src": { "main.rs": "fn main() {}" }
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
fs.set_branch_name(Path::new("/project/.git"), Some("main"));
|
||||
fs.insert_branches(Path::new("/project/.git"), &["main", "feature"]);
|
||||
|
||||
fs.add_linked_worktree_for_repo(
|
||||
Path::new("/project/.git"),
|
||||
true,
|
||||
GitWorktree {
|
||||
path: PathBuf::from("/external-worktree"),
|
||||
ref_name: Some("refs/heads/feature".into()),
|
||||
sha: "abc123".into(),
|
||||
is_main: false,
|
||||
is_bare: false,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let project = Project::test(
|
||||
fs.clone(),
|
||||
[Path::new("/project"), Path::new("/external-worktree")],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
project
|
||||
.update(cx, |project, cx| project.git_scans_complete(cx))
|
||||
.await;
|
||||
|
||||
let multi_workspace =
|
||||
cx.add_window(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
|
||||
let workspace = multi_workspace
|
||||
.read_with(cx, |mw, _cx| mw.workspace().clone())
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
workspace.read_with(cx, |_workspace, cx| {
|
||||
let plan = build_root_plan(
|
||||
Path::new("/external-worktree"),
|
||||
std::slice::from_ref(&workspace),
|
||||
cx,
|
||||
);
|
||||
assert!(
|
||||
plan.is_none(),
|
||||
"build_root_plan should return None for a linked worktree \
|
||||
outside the Zed-managed worktrees directory",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_build_root_plan_with_custom_worktree_directory(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
// Override the worktree_directory setting to a non-default location.
|
||||
// With main repo at /project and setting "../custom-worktrees", the
|
||||
// resolved base is /custom-worktrees/project.
|
||||
cx.update(|cx| {
|
||||
cx.update_global::<SettingsStore, _>(|store, cx| {
|
||||
store.update_user_settings(cx, |s| {
|
||||
s.git.get_or_insert(Default::default()).worktree_directory =
|
||||
Some("../custom-worktrees".to_string());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
"/project",
|
||||
json!({
|
||||
".git": {},
|
||||
"src": { "main.rs": "fn main() {}" }
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
fs.set_branch_name(Path::new("/project/.git"), Some("main"));
|
||||
fs.insert_branches(Path::new("/project/.git"), &["main", "feature", "feature2"]);
|
||||
|
||||
// Worktree inside the custom managed directory.
|
||||
fs.add_linked_worktree_for_repo(
|
||||
Path::new("/project/.git"),
|
||||
true,
|
||||
GitWorktree {
|
||||
path: PathBuf::from("/custom-worktrees/project/feature/project"),
|
||||
ref_name: Some("refs/heads/feature".into()),
|
||||
sha: "abc123".into(),
|
||||
is_main: false,
|
||||
is_bare: false,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
// Worktree outside the custom managed directory (at the default
|
||||
// `../worktrees` location, which is not what the setting says).
|
||||
fs.add_linked_worktree_for_repo(
|
||||
Path::new("/project/.git"),
|
||||
true,
|
||||
GitWorktree {
|
||||
path: PathBuf::from("/worktrees/project/feature2/project"),
|
||||
ref_name: Some("refs/heads/feature2".into()),
|
||||
sha: "def456".into(),
|
||||
is_main: false,
|
||||
is_bare: false,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
let project = Project::test(
|
||||
fs.clone(),
|
||||
[
|
||||
Path::new("/project"),
|
||||
Path::new("/custom-worktrees/project/feature/project"),
|
||||
Path::new("/worktrees/project/feature2/project"),
|
||||
],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
project
|
||||
.update(cx, |project, cx| project.git_scans_complete(cx))
|
||||
.await;
|
||||
|
||||
let multi_workspace =
|
||||
cx.add_window(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
|
||||
let workspace = multi_workspace
|
||||
.read_with(cx, |mw, _cx| mw.workspace().clone())
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
workspace.read_with(cx, |_workspace, cx| {
|
||||
// Worktree inside the custom managed directory SHOULD be archivable.
|
||||
let plan = build_root_plan(
|
||||
Path::new("/custom-worktrees/project/feature/project"),
|
||||
std::slice::from_ref(&workspace),
|
||||
cx,
|
||||
);
|
||||
assert!(
|
||||
plan.is_some(),
|
||||
"build_root_plan should return Some for a worktree inside \
|
||||
the custom worktree_directory",
|
||||
);
|
||||
|
||||
// Worktree at the default location SHOULD NOT be archivable
|
||||
// because the setting points elsewhere.
|
||||
let plan = build_root_plan(
|
||||
Path::new("/worktrees/project/feature2/project"),
|
||||
std::slice::from_ref(&workspace),
|
||||
cx,
|
||||
);
|
||||
assert!(
|
||||
plan.is_none(),
|
||||
"build_root_plan should return None for a worktree outside \
|
||||
the custom worktree_directory, even if it would match the default",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_remove_root_deletes_directory_and_git_metadata(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
|
|
@ -1070,7 +1262,7 @@ mod tests {
|
|||
Path::new("/project/.git"),
|
||||
true,
|
||||
GitWorktree {
|
||||
path: PathBuf::from("/linked-worktree"),
|
||||
path: PathBuf::from("/worktrees/project/feature/project"),
|
||||
ref_name: Some("refs/heads/feature".into()),
|
||||
sha: "abc123".into(),
|
||||
is_main: false,
|
||||
|
|
@ -1081,7 +1273,10 @@ mod tests {
|
|||
|
||||
let project = Project::test(
|
||||
fs.clone(),
|
||||
[Path::new("/project"), Path::new("/linked-worktree")],
|
||||
[
|
||||
Path::new("/project"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
|
@ -1101,14 +1296,17 @@ mod tests {
|
|||
let root = workspace
|
||||
.read_with(cx, |_workspace, cx| {
|
||||
build_root_plan(
|
||||
Path::new("/linked-worktree"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
std::slice::from_ref(&workspace),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.expect("should produce a root plan for the linked worktree");
|
||||
|
||||
assert!(fs.is_dir(Path::new("/linked-worktree")).await);
|
||||
assert!(
|
||||
fs.is_dir(Path::new("/worktrees/project/feature/project"))
|
||||
.await
|
||||
);
|
||||
|
||||
// Remove the root.
|
||||
let task = cx.update(|cx| cx.spawn(async move |cx| remove_root(root, cx).await));
|
||||
|
|
@ -1119,7 +1317,8 @@ mod tests {
|
|||
// The FakeFs directory should be gone (removed by the FakeGitRepository
|
||||
// backend's remove_worktree implementation).
|
||||
assert!(
|
||||
!fs.is_dir(Path::new("/linked-worktree")).await,
|
||||
!fs.is_dir(Path::new("/worktrees/project/feature/project"))
|
||||
.await,
|
||||
"linked worktree directory should be removed from FakeFs"
|
||||
);
|
||||
}
|
||||
|
|
@ -1144,7 +1343,7 @@ mod tests {
|
|||
Path::new("/project/.git"),
|
||||
true,
|
||||
GitWorktree {
|
||||
path: PathBuf::from("/linked-worktree"),
|
||||
path: PathBuf::from("/worktrees/project/feature/project"),
|
||||
ref_name: Some("refs/heads/feature".into()),
|
||||
sha: "abc123".into(),
|
||||
is_main: false,
|
||||
|
|
@ -1155,7 +1354,10 @@ mod tests {
|
|||
|
||||
let project = Project::test(
|
||||
fs.clone(),
|
||||
[Path::new("/project"), Path::new("/linked-worktree")],
|
||||
[
|
||||
Path::new("/project"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
|
@ -1174,7 +1376,7 @@ mod tests {
|
|||
let root = workspace
|
||||
.read_with(cx, |_workspace, cx| {
|
||||
build_root_plan(
|
||||
Path::new("/linked-worktree"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
std::slice::from_ref(&workspace),
|
||||
cx,
|
||||
)
|
||||
|
|
@ -1185,7 +1387,7 @@ mod tests {
|
|||
// remove_root, simulating the directory being deleted externally.
|
||||
fs.as_ref()
|
||||
.remove_dir(
|
||||
Path::new("/linked-worktree"),
|
||||
Path::new("/worktrees/project/feature/project"),
|
||||
fs::RemoveOptions {
|
||||
recursive: true,
|
||||
ignore_if_not_exists: false,
|
||||
|
|
@ -1193,7 +1395,11 @@ mod tests {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(!fs.as_ref().is_dir(Path::new("/linked-worktree")).await);
|
||||
assert!(
|
||||
!fs.as_ref()
|
||||
.is_dir(Path::new("/worktrees/project/feature/project"))
|
||||
.await
|
||||
);
|
||||
|
||||
// remove_root should still succeed — the std::fs::remove_dir_all
|
||||
// handles NotFound, and git worktree remove handles a missing
|
||||
|
|
|
|||
|
|
@ -4549,7 +4549,7 @@ async fn test_archive_last_worktree_thread_removes_workspace(cx: &mut TestAppCon
|
|||
.await;
|
||||
|
||||
fs.insert_tree(
|
||||
"/wt-feature-a",
|
||||
"/worktrees/project/feature-a/project",
|
||||
serde_json::json!({
|
||||
".git": "gitdir: /project/.git/worktrees/feature-a",
|
||||
"src": {},
|
||||
|
|
@ -4561,7 +4561,7 @@ async fn test_archive_last_worktree_thread_removes_workspace(cx: &mut TestAppCon
|
|||
Path::new("/project/.git"),
|
||||
false,
|
||||
git::repository::Worktree {
|
||||
path: PathBuf::from("/wt-feature-a"),
|
||||
path: PathBuf::from("/worktrees/project/feature-a/project"),
|
||||
ref_name: Some("refs/heads/feature-a".into()),
|
||||
sha: "abc".into(),
|
||||
is_main: false,
|
||||
|
|
@ -4573,7 +4573,12 @@ async fn test_archive_last_worktree_thread_removes_workspace(cx: &mut TestAppCon
|
|||
cx.update(|cx| <dyn fs::Fs>::set_global(fs.clone(), cx));
|
||||
|
||||
let main_project = project::Project::test(fs.clone(), ["/project".as_ref()], cx).await;
|
||||
let worktree_project = project::Project::test(fs.clone(), ["/wt-feature-a".as_ref()], cx).await;
|
||||
let worktree_project = project::Project::test(
|
||||
fs.clone(),
|
||||
["/worktrees/project/feature-a/project".as_ref()],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
||||
main_project
|
||||
.update(cx, |p, cx| p.git_scans_complete(cx))
|
||||
|
|
@ -4643,7 +4648,8 @@ async fn test_archive_last_worktree_thread_removes_workspace(cx: &mut TestAppCon
|
|||
|
||||
// The linked worktree checkout directory should also be removed from disk.
|
||||
assert!(
|
||||
!fs.is_dir(Path::new("/wt-feature-a")).await,
|
||||
!fs.is_dir(Path::new("/worktrees/project/feature-a/project"))
|
||||
.await,
|
||||
"linked worktree directory should be removed from disk after archiving its last thread"
|
||||
);
|
||||
|
||||
|
|
@ -4677,7 +4683,7 @@ async fn test_archive_last_worktree_thread_removes_workspace(cx: &mut TestAppCon
|
|||
});
|
||||
assert_eq!(
|
||||
archived_paths.paths(),
|
||||
&[PathBuf::from("/wt-feature-a")],
|
||||
&[PathBuf::from("/worktrees/project/feature-a/project")],
|
||||
"archived thread must retain its folder_paths for restore"
|
||||
);
|
||||
}
|
||||
|
|
@ -9892,7 +9898,7 @@ async fn test_archive_removes_worktree_even_when_workspace_paths_diverge(cx: &mu
|
|||
.await;
|
||||
|
||||
fs.insert_tree(
|
||||
"/wt-feature-a",
|
||||
"/worktrees/project/feature-a/project",
|
||||
serde_json::json!({
|
||||
".git": "gitdir: /project/.git/worktrees/feature-a",
|
||||
"src": {
|
||||
|
|
@ -9906,7 +9912,7 @@ async fn test_archive_removes_worktree_even_when_workspace_paths_diverge(cx: &mu
|
|||
Path::new("/project/.git"),
|
||||
false,
|
||||
git::repository::Worktree {
|
||||
path: PathBuf::from("/wt-feature-a"),
|
||||
path: PathBuf::from("/worktrees/project/feature-a/project"),
|
||||
ref_name: Some("refs/heads/feature-a".into()),
|
||||
sha: "abc".into(),
|
||||
is_main: false,
|
||||
|
|
@ -9918,7 +9924,12 @@ async fn test_archive_removes_worktree_even_when_workspace_paths_diverge(cx: &mu
|
|||
cx.update(|cx| <dyn fs::Fs>::set_global(fs.clone(), cx));
|
||||
|
||||
let main_project = project::Project::test(fs.clone(), ["/project".as_ref()], cx).await;
|
||||
let worktree_project = project::Project::test(fs.clone(), ["/wt-feature-a".as_ref()], cx).await;
|
||||
let worktree_project = project::Project::test(
|
||||
fs.clone(),
|
||||
["/worktrees/project/feature-a/project".as_ref()],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
||||
main_project
|
||||
.update(cx, |p, cx| p.git_scans_complete(cx))
|
||||
|
|
@ -9945,7 +9956,7 @@ async fn test_archive_removes_worktree_even_when_workspace_paths_diverge(cx: &mu
|
|||
"worktree-thread",
|
||||
"Worktree Thread",
|
||||
PathList::new(&[
|
||||
PathBuf::from("/wt-feature-a"),
|
||||
PathBuf::from("/worktrees/project/feature-a/project"),
|
||||
PathBuf::from("/nonexistent"),
|
||||
]),
|
||||
PathList::new(&[PathBuf::from("/project"), PathBuf::from("/nonexistent")]),
|
||||
|
|
@ -10004,7 +10015,8 @@ async fn test_archive_removes_worktree_even_when_workspace_paths_diverge(cx: &mu
|
|||
|
||||
// The linked worktree directory should be removed from disk.
|
||||
assert!(
|
||||
!fs.is_dir(Path::new("/wt-feature-a")).await,
|
||||
!fs.is_dir(Path::new("/worktrees/project/feature-a/project"))
|
||||
.await,
|
||||
"linked worktree directory should be removed from disk"
|
||||
);
|
||||
}
|
||||
|
|
@ -10037,7 +10049,7 @@ async fn test_archive_mixed_workspace_closes_only_archived_worktree_items(cx: &m
|
|||
.await;
|
||||
|
||||
fs.insert_tree(
|
||||
"/wt-feature-b",
|
||||
"/worktrees/main-repo/feature-b/main-repo",
|
||||
serde_json::json!({
|
||||
".git": "gitdir: /main-repo/.git/worktrees/feature-b",
|
||||
"src": {
|
||||
|
|
@ -10051,7 +10063,7 @@ async fn test_archive_mixed_workspace_closes_only_archived_worktree_items(cx: &m
|
|||
Path::new("/main-repo/.git"),
|
||||
false,
|
||||
git::repository::Worktree {
|
||||
path: PathBuf::from("/wt-feature-b"),
|
||||
path: PathBuf::from("/worktrees/main-repo/feature-b/main-repo"),
|
||||
ref_name: Some("refs/heads/feature-b".into()),
|
||||
sha: "def".into(),
|
||||
is_main: false,
|
||||
|
|
@ -10066,7 +10078,10 @@ async fn test_archive_mixed_workspace_closes_only_archived_worktree_items(cx: &m
|
|||
// linked worktree — this makes it a "mixed" workspace.
|
||||
let mixed_project = project::Project::test(
|
||||
fs.clone(),
|
||||
["/main-repo".as_ref(), "/wt-feature-b".as_ref()],
|
||||
[
|
||||
"/main-repo".as_ref(),
|
||||
"/worktrees/main-repo/feature-b/main-repo".as_ref(),
|
||||
],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
|
|
@ -10093,15 +10108,15 @@ async fn test_archive_mixed_workspace_closes_only_archived_worktree_items(cx: &m
|
|||
|
||||
let main_repo_wt_id = worktree_ids
|
||||
.iter()
|
||||
.find(|(_, path)| path.ends_with("main-repo"))
|
||||
.find(|(_, path)| path.as_ref() == Path::new("/main-repo"))
|
||||
.map(|(id, _)| *id)
|
||||
.expect("should find main-repo worktree");
|
||||
|
||||
let feature_b_wt_id = worktree_ids
|
||||
.iter()
|
||||
.find(|(_, path)| path.ends_with("wt-feature-b"))
|
||||
.find(|(_, path)| path.as_ref() == Path::new("/worktrees/main-repo/feature-b/main-repo"))
|
||||
.map(|(id, _)| *id)
|
||||
.expect("should find wt-feature-b worktree");
|
||||
.expect("should find feature-b worktree");
|
||||
|
||||
// Open files from both worktrees.
|
||||
let main_repo_path = project::ProjectPath {
|
||||
|
|
@ -10158,7 +10173,7 @@ async fn test_archive_mixed_workspace_closes_only_archived_worktree_items(cx: &m
|
|||
"feature-b-thread",
|
||||
"Feature B Thread",
|
||||
PathList::new(&[
|
||||
PathBuf::from("/wt-feature-b"),
|
||||
PathBuf::from("/worktrees/main-repo/feature-b/main-repo"),
|
||||
PathBuf::from("/nonexistent"),
|
||||
]),
|
||||
PathList::new(&[PathBuf::from("/main-repo"), PathBuf::from("/nonexistent")]),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue