diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 7823a99e82b8f5394bbfcb66ae8deb1e20709515..0d2df99595d8400789c21c433f21ca3c8f1ab2d8 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -2812,6 +2812,61 @@ mod tests { }) } + #[gpui::test] + async fn test_circular_symlinks(cx: &mut TestAppContext) { + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/root", + json!({ + "lib": { + "a": { + "a.txt": "" + }, + "b": { + "b.txt": "" + } + } + }), + ) + .await; + fs.insert_symlink("/root/lib/a/lib", "..".into()).await; + fs.insert_symlink("/root/lib/b/lib", "..".into()).await; + + let http_client = FakeHttpClient::with_404_response(); + let client = Client::new(http_client); + let tree = Worktree::local( + client, + Arc::from(Path::new("/root")), + true, + fs, + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + + cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) + .await; + + tree.read_with(cx, |tree, _| { + assert_eq!( + tree.entries(false) + .map(|entry| entry.path.as_ref()) + .collect::>(), + vec![ + Path::new(""), + Path::new("lib"), + Path::new("lib/a"), + Path::new("lib/a/a.txt"), + Path::new("lib/a/lib"), + Path::new("lib/b"), + Path::new("lib/b/b.txt"), + Path::new("lib/b/lib"), + ] + ); + }) + } + #[gpui::test] async fn test_rescan_with_gitignore(cx: &mut TestAppContext) { let parent_dir = temp_tree(json!({