Detailed changes
@@ -453,220 +453,208 @@ impl FileFinder {
mod tests {
use super::*;
use crate::{editor, settings, test::temp_tree, workspace::Workspace};
- use gpui::App;
use serde_json::json;
use std::fs;
use tempdir::TempDir;
- #[test]
- fn test_matching_paths() {
- App::test_async((), |mut app| async move {
- let tmp_dir = TempDir::new("example").unwrap();
- fs::create_dir(tmp_dir.path().join("a")).unwrap();
- fs::write(tmp_dir.path().join("a/banana"), "banana").unwrap();
- fs::write(tmp_dir.path().join("a/bandana"), "bandana").unwrap();
- app.update(|ctx| {
- super::init(ctx);
- editor::init(ctx);
- });
-
- let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (window_id, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings, ctx);
- workspace.add_worktree(tmp_dir.path(), ctx);
- workspace
- });
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
- app.dispatch_action(
- window_id,
- vec![workspace.id()],
- "file_finder:toggle".into(),
- (),
- );
+ #[gpui::test]
+ async fn test_matching_paths(mut app: gpui::TestAppContext) {
+ let tmp_dir = TempDir::new("example").unwrap();
+ fs::create_dir(tmp_dir.path().join("a")).unwrap();
+ fs::write(tmp_dir.path().join("a/banana"), "banana").unwrap();
+ fs::write(tmp_dir.path().join("a/bandana"), "bandana").unwrap();
+ app.update(|ctx| {
+ super::init(ctx);
+ editor::init(ctx);
+ });
- let finder = app.read(|ctx| {
- workspace
- .read(ctx)
- .modal()
- .cloned()
- .unwrap()
- .downcast::<FileFinder>()
- .unwrap()
- });
- let query_buffer = app.read(|ctx| finder.read(ctx).query_buffer.clone());
-
- let chain = vec![finder.id(), query_buffer.id()];
- app.dispatch_action(window_id, chain.clone(), "buffer:insert", "b".to_string());
- app.dispatch_action(window_id, chain.clone(), "buffer:insert", "n".to_string());
- app.dispatch_action(window_id, chain.clone(), "buffer:insert", "a".to_string());
- finder
- .condition(&app, |finder, _| finder.matches.len() == 2)
- .await;
-
- let active_pane = app.read(|ctx| workspace.read(ctx).active_pane().clone());
- app.dispatch_action(
- window_id,
- vec![workspace.id(), finder.id()],
- "menu:select_next",
- (),
- );
- app.dispatch_action(
- window_id,
- vec![workspace.id(), finder.id()],
- "file_finder:confirm",
- (),
- );
- active_pane
- .condition(&app, |pane, _| pane.active_item().is_some())
- .await;
- app.read(|ctx| {
- let active_item = active_pane.read(ctx).active_item().unwrap();
- assert_eq!(active_item.title(ctx), "bandana");
- });
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
+ let (window_id, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings, ctx);
+ workspace.add_worktree(tmp_dir.path(), ctx);
+ workspace
+ });
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
+ .await;
+ app.dispatch_action(
+ window_id,
+ vec![workspace.id()],
+ "file_finder:toggle".into(),
+ (),
+ );
+
+ let finder = app.read(|ctx| {
+ workspace
+ .read(ctx)
+ .modal()
+ .cloned()
+ .unwrap()
+ .downcast::<FileFinder>()
+ .unwrap()
+ });
+ let query_buffer = app.read(|ctx| finder.read(ctx).query_buffer.clone());
+
+ let chain = vec![finder.id(), query_buffer.id()];
+ app.dispatch_action(window_id, chain.clone(), "buffer:insert", "b".to_string());
+ app.dispatch_action(window_id, chain.clone(), "buffer:insert", "n".to_string());
+ app.dispatch_action(window_id, chain.clone(), "buffer:insert", "a".to_string());
+ finder
+ .condition(&app, |finder, _| finder.matches.len() == 2)
+ .await;
+
+ let active_pane = app.read(|ctx| workspace.read(ctx).active_pane().clone());
+ app.dispatch_action(
+ window_id,
+ vec![workspace.id(), finder.id()],
+ "menu:select_next",
+ (),
+ );
+ app.dispatch_action(
+ window_id,
+ vec![workspace.id(), finder.id()],
+ "file_finder:confirm",
+ (),
+ );
+ active_pane
+ .condition(&app, |pane, _| pane.active_item().is_some())
+ .await;
+ app.read(|ctx| {
+ let active_item = active_pane.read(ctx).active_item().unwrap();
+ assert_eq!(active_item.title(ctx), "bandana");
});
}
- #[test]
- fn test_matching_cancellation() {
- App::test_async((), |mut app| async move {
- let tmp_dir = temp_tree(json!({
- "hello": "",
- "goodbye": "",
- "halogen-light": "",
- "happiness": "",
- "height": "",
- "hi": "",
- "hiccup": "",
- }));
- let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (_, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings.clone(), ctx);
- workspace.add_worktree(tmp_dir.path(), ctx);
- workspace
- });
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
- let (_, finder) =
- app.add_window(|ctx| FileFinder::new(settings, workspace.clone(), ctx));
-
- let query = "hi".to_string();
- finder.update(&mut app, |f, ctx| f.spawn_search(query.clone(), ctx));
- finder.condition(&app, |f, _| f.matches.len() == 5).await;
-
- finder.update(&mut app, |finder, ctx| {
- let matches = finder.matches.clone();
-
- // Simulate a search being cancelled after the time limit,
- // returning only a subset of the matches that would have been found.
- finder.spawn_search(query.clone(), ctx);
- finder.update_matches(
- (
- finder.latest_search_id,
- true, // did-cancel
- query.clone(),
- vec![matches[1].clone(), matches[3].clone()],
- ),
- ctx,
- );
-
- // Simulate another cancellation.
- finder.spawn_search(query.clone(), ctx);
- finder.update_matches(
- (
- finder.latest_search_id,
- true, // did-cancel
- query.clone(),
- vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
- ),
- ctx,
- );
+ #[gpui::test]
+ async fn test_matching_cancellation(mut app: gpui::TestAppContext) {
+ let tmp_dir = temp_tree(json!({
+ "hello": "",
+ "goodbye": "",
+ "halogen-light": "",
+ "happiness": "",
+ "height": "",
+ "hi": "",
+ "hiccup": "",
+ }));
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
+ let (_, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings.clone(), ctx);
+ workspace.add_worktree(tmp_dir.path(), ctx);
+ workspace
+ });
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
+ .await;
+ let (_, finder) = app.add_window(|ctx| FileFinder::new(settings, workspace.clone(), ctx));
+
+ let query = "hi".to_string();
+ finder.update(&mut app, |f, ctx| f.spawn_search(query.clone(), ctx));
+ finder.condition(&app, |f, _| f.matches.len() == 5).await;
+
+ finder.update(&mut app, |finder, ctx| {
+ let matches = finder.matches.clone();
+
+ // Simulate a search being cancelled after the time limit,
+ // returning only a subset of the matches that would have been found.
+ finder.spawn_search(query.clone(), ctx);
+ finder.update_matches(
+ (
+ finder.latest_search_id,
+ true, // did-cancel
+ query.clone(),
+ vec![matches[1].clone(), matches[3].clone()],
+ ),
+ ctx,
+ );
- assert_eq!(finder.matches, matches[0..4])
- });
+ // Simulate another cancellation.
+ finder.spawn_search(query.clone(), ctx);
+ finder.update_matches(
+ (
+ finder.latest_search_id,
+ true, // did-cancel
+ query.clone(),
+ vec![matches[0].clone(), matches[2].clone(), matches[3].clone()],
+ ),
+ ctx,
+ );
+
+ assert_eq!(finder.matches, matches[0..4])
});
}
- #[test]
- fn test_single_file_worktrees() {
- App::test_async((), |mut app| async move {
- let temp_dir = TempDir::new("test-single-file-worktrees").unwrap();
- let dir_path = temp_dir.path().join("the-parent-dir");
- let file_path = dir_path.join("the-file");
- fs::create_dir(&dir_path).unwrap();
- fs::write(&file_path, "").unwrap();
-
- let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (_, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings.clone(), ctx);
- workspace.add_worktree(&file_path, ctx);
- workspace
- });
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
- let (_, finder) =
- app.add_window(|ctx| FileFinder::new(settings, workspace.clone(), ctx));
-
- // Even though there is only one worktree, that worktree's filename
- // is included in the matching, because the worktree is a single file.
- finder.update(&mut app, |f, ctx| f.spawn_search("thf".into(), ctx));
- finder.condition(&app, |f, _| f.matches.len() == 1).await;
-
- app.read(|ctx| {
- let finder = finder.read(ctx);
- let (file_name, file_name_positions, full_path, full_path_positions) =
- finder.labels_for_match(&finder.matches[0], ctx).unwrap();
-
- assert_eq!(file_name, "the-file");
- assert_eq!(file_name_positions, &[0, 1, 4]);
- assert_eq!(full_path, "the-file");
- assert_eq!(full_path_positions, &[0, 1, 4]);
- });
-
- // Since the worktree root is a file, searching for its name followed by a slash does
- // not match anything.
- finder.update(&mut app, |f, ctx| f.spawn_search("thf/".into(), ctx));
- finder.condition(&app, |f, _| f.matches.len() == 0).await;
+ #[gpui::test]
+ async fn test_single_file_worktrees(mut app: gpui::TestAppContext) {
+ let temp_dir = TempDir::new("test-single-file-worktrees").unwrap();
+ let dir_path = temp_dir.path().join("the-parent-dir");
+ let file_path = dir_path.join("the-file");
+ fs::create_dir(&dir_path).unwrap();
+ fs::write(&file_path, "").unwrap();
+
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
+ let (_, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings.clone(), ctx);
+ workspace.add_worktree(&file_path, ctx);
+ workspace
});
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
+ .await;
+ let (_, finder) = app.add_window(|ctx| FileFinder::new(settings, workspace.clone(), ctx));
+
+ // Even though there is only one worktree, that worktree's filename
+ // is included in the matching, because the worktree is a single file.
+ finder.update(&mut app, |f, ctx| f.spawn_search("thf".into(), ctx));
+ finder.condition(&app, |f, _| f.matches.len() == 1).await;
+
+ app.read(|ctx| {
+ let finder = finder.read(ctx);
+ let (file_name, file_name_positions, full_path, full_path_positions) =
+ finder.labels_for_match(&finder.matches[0], ctx).unwrap();
+
+ assert_eq!(file_name, "the-file");
+ assert_eq!(file_name_positions, &[0, 1, 4]);
+ assert_eq!(full_path, "the-file");
+ assert_eq!(full_path_positions, &[0, 1, 4]);
+ });
+
+ // Since the worktree root is a file, searching for its name followed by a slash does
+ // not match anything.
+ finder.update(&mut app, |f, ctx| f.spawn_search("thf/".into(), ctx));
+ finder.condition(&app, |f, _| f.matches.len() == 0).await;
}
- #[test]
- fn test_multiple_matches_with_same_relative_path() {
- App::test_async((), |mut app| async move {
- let tmp_dir = temp_tree(json!({
- "dir1": { "a.txt": "" },
- "dir2": { "a.txt": "" }
- }));
- let settings = settings::channel(&app.font_cache()).unwrap().1;
+ #[gpui::test]
+ async fn test_multiple_matches_with_same_relative_path(mut app: gpui::TestAppContext) {
+ let tmp_dir = temp_tree(json!({
+ "dir1": { "a.txt": "" },
+ "dir2": { "a.txt": "" }
+ }));
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (_, workspace) = app.add_window(|ctx| Workspace::new(0, settings.clone(), ctx));
+ let (_, workspace) = app.add_window(|ctx| Workspace::new(0, settings.clone(), ctx));
- workspace
- .update(&mut app, |workspace, ctx| {
- workspace.open_paths(
- &[tmp_dir.path().join("dir1"), tmp_dir.path().join("dir2")],
- ctx,
- )
- })
- .await;
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
-
- let (_, finder) =
- app.add_window(|ctx| FileFinder::new(settings, workspace.clone(), ctx));
-
- // Run a search that matches two files with the same relative path.
- finder.update(&mut app, |f, ctx| f.spawn_search("a.t".into(), ctx));
- finder.condition(&app, |f, _| f.matches.len() == 2).await;
-
- // Can switch between different matches with the same relative path.
- finder.update(&mut app, |f, ctx| {
- assert_eq!(f.selected_index(), 0);
- f.select_next(&(), ctx);
- assert_eq!(f.selected_index(), 1);
- f.select_prev(&(), ctx);
- assert_eq!(f.selected_index(), 0);
- });
+ workspace
+ .update(&mut app, |workspace, ctx| {
+ workspace.open_paths(
+ &[tmp_dir.path().join("dir1"), tmp_dir.path().join("dir2")],
+ ctx,
+ )
+ })
+ .await;
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
+ .await;
+
+ let (_, finder) = app.add_window(|ctx| FileFinder::new(settings, workspace.clone(), ctx));
+
+ // Run a search that matches two files with the same relative path.
+ finder.update(&mut app, |f, ctx| f.spawn_search("a.t".into(), ctx));
+ finder.condition(&app, |f, _| f.matches.len() == 2).await;
+
+ // Can switch between different matches with the same relative path.
+ finder.update(&mut app, |f, ctx| {
+ assert_eq!(f.selected_index(), 0);
+ f.select_next(&(), ctx);
+ assert_eq!(f.selected_index(), 1);
+ f.select_prev(&(), ctx);
+ assert_eq!(f.selected_index(), 0);
});
}
}
@@ -729,7 +729,6 @@ impl WorkspaceHandle for ViewHandle<Workspace> {
mod tests {
use super::*;
use crate::{editor::BufferView, settings, test::temp_tree};
- use gpui::App;
use serde_json::json;
use std::collections::HashSet;
use tempdir::TempDir;
@@ -793,332 +792,324 @@ mod tests {
assert_eq!(app.window_ids().count(), 2);
}
- #[test]
- fn test_open_entry() {
- App::test_async((), |mut app| async move {
- let dir = temp_tree(json!({
- "a": {
- "file1": "contents 1",
- "file2": "contents 2",
- "file3": "contents 3",
- },
- }));
-
- let settings = settings::channel(&app.font_cache()).unwrap().1;
-
- let (_, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings, ctx);
- workspace.add_worktree(dir.path(), ctx);
- workspace
- });
-
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
- let entries = app.read(|ctx| workspace.file_entries(ctx));
- let file1 = entries[0].clone();
- let file2 = entries[1].clone();
- let file3 = entries[2].clone();
+ #[gpui::test]
+ async fn test_open_entry(mut app: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ "a": {
+ "file1": "contents 1",
+ "file2": "contents 2",
+ "file3": "contents 3",
+ },
+ }));
- // Open the first entry
- workspace
- .update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx))
- .unwrap()
- .await;
- app.read(|ctx| {
- let pane = workspace.read(ctx).active_pane().read(ctx);
- assert_eq!(
- pane.active_item().unwrap().entry_id(ctx),
- Some(file1.clone())
- );
- assert_eq!(pane.items().len(), 1);
- });
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
- // Open the second entry
+ let (_, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings, ctx);
+ workspace.add_worktree(dir.path(), ctx);
workspace
- .update(&mut app, |w, ctx| w.open_entry(file2.clone(), ctx))
- .unwrap()
- .await;
- app.read(|ctx| {
- let pane = workspace.read(ctx).active_pane().read(ctx);
- assert_eq!(
- pane.active_item().unwrap().entry_id(ctx),
- Some(file2.clone())
- );
- assert_eq!(pane.items().len(), 2);
- });
-
- // Open the first entry again. The existing pane item is activated.
- workspace.update(&mut app, |w, ctx| {
- assert!(w.open_entry(file1.clone(), ctx).is_none())
- });
- app.read(|ctx| {
- let pane = workspace.read(ctx).active_pane().read(ctx);
- assert_eq!(
- pane.active_item().unwrap().entry_id(ctx),
- Some(file1.clone())
- );
- assert_eq!(pane.items().len(), 2);
- });
-
- // Split the pane with the first entry, then open the second entry again.
- workspace.update(&mut app, |w, ctx| {
- w.split_pane(w.active_pane().clone(), SplitDirection::Right, ctx);
- assert!(w.open_entry(file2.clone(), ctx).is_none());
- assert_eq!(
- w.active_pane()
- .read(ctx)
- .active_item()
- .unwrap()
- .entry_id(ctx.as_ref()),
- Some(file2.clone())
- );
- });
-
- // Open the third entry twice concurrently. Two pane items
- // are added.
- let (t1, t2) = workspace.update(&mut app, |w, ctx| {
- (
- w.open_entry(file3.clone(), ctx).unwrap(),
- w.open_entry(file3.clone(), ctx).unwrap(),
- )
- });
- t1.await;
- t2.await;
- app.read(|ctx| {
- let pane = workspace.read(ctx).active_pane().read(ctx);
- assert_eq!(
- pane.active_item().unwrap().entry_id(ctx),
- Some(file3.clone())
- );
- let pane_entries = pane
- .items()
- .iter()
- .map(|i| i.entry_id(ctx).unwrap())
- .collect::<Vec<_>>();
- assert_eq!(pane_entries, &[file1, file2, file3.clone(), file3]);
- });
});
- }
- #[test]
- fn test_open_paths() {
- App::test_async((), |mut app| async move {
- let dir1 = temp_tree(json!({
- "a.txt": "",
- }));
- let dir2 = temp_tree(json!({
- "b.txt": "",
- }));
-
- let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (_, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings, ctx);
- workspace.add_worktree(dir1.path(), ctx);
- workspace
- });
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
-
- // Open a file within an existing worktree.
- app.update(|ctx| {
- workspace.update(ctx, |view, ctx| {
- view.open_paths(&[dir1.path().join("a.txt")], ctx)
- })
- })
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
.await;
- app.read(|ctx| {
- assert_eq!(
- workspace
- .read(ctx)
- .active_pane()
- .read(ctx)
- .active_item()
- .unwrap()
- .title(ctx),
- "a.txt"
- );
- });
+ let entries = app.read(|ctx| workspace.file_entries(ctx));
+ let file1 = entries[0].clone();
+ let file2 = entries[1].clone();
+ let file3 = entries[2].clone();
+
+ // Open the first entry
+ workspace
+ .update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx))
+ .unwrap()
+ .await;
+ app.read(|ctx| {
+ let pane = workspace.read(ctx).active_pane().read(ctx);
+ assert_eq!(
+ pane.active_item().unwrap().entry_id(ctx),
+ Some(file1.clone())
+ );
+ assert_eq!(pane.items().len(), 1);
+ });
- // Open a file outside of any existing worktree.
- app.update(|ctx| {
- workspace.update(ctx, |view, ctx| {
- view.open_paths(&[dir2.path().join("b.txt")], ctx)
- })
- })
+ // Open the second entry
+ workspace
+ .update(&mut app, |w, ctx| w.open_entry(file2.clone(), ctx))
+ .unwrap()
.await;
- app.read(|ctx| {
- let worktree_roots = workspace
+ app.read(|ctx| {
+ let pane = workspace.read(ctx).active_pane().read(ctx);
+ assert_eq!(
+ pane.active_item().unwrap().entry_id(ctx),
+ Some(file2.clone())
+ );
+ assert_eq!(pane.items().len(), 2);
+ });
+
+ // Open the first entry again. The existing pane item is activated.
+ workspace.update(&mut app, |w, ctx| {
+ assert!(w.open_entry(file1.clone(), ctx).is_none())
+ });
+ app.read(|ctx| {
+ let pane = workspace.read(ctx).active_pane().read(ctx);
+ assert_eq!(
+ pane.active_item().unwrap().entry_id(ctx),
+ Some(file1.clone())
+ );
+ assert_eq!(pane.items().len(), 2);
+ });
+
+ // Split the pane with the first entry, then open the second entry again.
+ workspace.update(&mut app, |w, ctx| {
+ w.split_pane(w.active_pane().clone(), SplitDirection::Right, ctx);
+ assert!(w.open_entry(file2.clone(), ctx).is_none());
+ assert_eq!(
+ w.active_pane()
.read(ctx)
- .worktrees()
- .iter()
- .map(|w| w.read(ctx).abs_path())
- .collect::<HashSet<_>>();
- assert_eq!(
- worktree_roots,
- vec![dir1.path(), &dir2.path().join("b.txt")]
- .into_iter()
- .collect(),
- );
- assert_eq!(
- workspace
- .read(ctx)
- .active_pane()
- .read(ctx)
- .active_item()
- .unwrap()
- .title(ctx),
- "b.txt"
- );
- });
+ .active_item()
+ .unwrap()
+ .entry_id(ctx.as_ref()),
+ Some(file2.clone())
+ );
+ });
+
+ // Open the third entry twice concurrently. Two pane items
+ // are added.
+ let (t1, t2) = workspace.update(&mut app, |w, ctx| {
+ (
+ w.open_entry(file3.clone(), ctx).unwrap(),
+ w.open_entry(file3.clone(), ctx).unwrap(),
+ )
+ });
+ t1.await;
+ t2.await;
+ app.read(|ctx| {
+ let pane = workspace.read(ctx).active_pane().read(ctx);
+ assert_eq!(
+ pane.active_item().unwrap().entry_id(ctx),
+ Some(file3.clone())
+ );
+ let pane_entries = pane
+ .items()
+ .iter()
+ .map(|i| i.entry_id(ctx).unwrap())
+ .collect::<Vec<_>>();
+ assert_eq!(pane_entries, &[file1, file2, file3.clone(), file3]);
});
}
- #[test]
- fn test_open_and_save_new_file() {
- App::test_async((), |mut app| async move {
- let dir = TempDir::new("test-new-file").unwrap();
- let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (_, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings, ctx);
- workspace.add_worktree(dir.path(), ctx);
- workspace
- });
- let tree = app.read(|ctx| {
+ #[gpui::test]
+ async fn test_open_paths(mut app: gpui::TestAppContext) {
+ let dir1 = temp_tree(json!({
+ "a.txt": "",
+ }));
+ let dir2 = temp_tree(json!({
+ "b.txt": "",
+ }));
+
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
+ let (_, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings, ctx);
+ workspace.add_worktree(dir1.path(), ctx);
+ workspace
+ });
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
+ .await;
+
+ // Open a file within an existing worktree.
+ app.update(|ctx| {
+ workspace.update(ctx, |view, ctx| {
+ view.open_paths(&[dir1.path().join("a.txt")], ctx)
+ })
+ })
+ .await;
+ app.read(|ctx| {
+ assert_eq!(
workspace
.read(ctx)
- .worktrees()
- .iter()
- .next()
+ .active_pane()
+ .read(ctx)
+ .active_item()
.unwrap()
- .clone()
- });
- tree.flush_fs_events(&app).await;
+ .title(ctx),
+ "a.txt"
+ );
+ });
- // Create a new untitled buffer
- let editor = workspace.update(&mut app, |workspace, ctx| {
- workspace.open_new_file(&(), ctx);
- workspace
- .active_item(ctx)
- .unwrap()
- .to_any()
- .downcast::<BufferView>()
- .unwrap()
- });
- editor.update(&mut app, |editor, ctx| {
- assert!(!editor.is_dirty(ctx.as_ref()));
- assert_eq!(editor.title(ctx.as_ref()), "untitled");
- editor.insert(&"hi".to_string(), ctx);
- assert!(editor.is_dirty(ctx.as_ref()));
- });
-
- // Save the buffer. This prompts for a filename.
- workspace.update(&mut app, |workspace, ctx| {
- workspace.save_active_item(&(), ctx)
- });
- app.simulate_new_path_selection(|parent_dir| {
- assert_eq!(parent_dir, dir.path());
- Some(parent_dir.join("the-new-name"))
- });
- app.read(|ctx| {
- assert!(editor.is_dirty(ctx));
- assert_eq!(editor.title(ctx), "untitled");
- });
-
- // When the save completes, the buffer's title is updated.
- tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
- .await;
- app.read(|ctx| {
- assert!(!editor.is_dirty(ctx));
- assert_eq!(editor.title(ctx), "the-new-name");
- });
-
- // Edit the file and save it again. This time, there is no filename prompt.
- editor.update(&mut app, |editor, ctx| {
- editor.insert(&" there".to_string(), ctx);
- assert_eq!(editor.is_dirty(ctx.as_ref()), true);
- });
- workspace.update(&mut app, |workspace, ctx| {
- workspace.save_active_item(&(), ctx)
- });
- assert!(!app.did_prompt_for_new_path());
- editor
- .condition(&app, |editor, ctx| !editor.is_dirty(ctx))
- .await;
- app.read(|ctx| assert_eq!(editor.title(ctx), "the-new-name"));
-
- // Open the same newly-created file in another pane item. The new editor should reuse
- // the same buffer.
- workspace.update(&mut app, |workspace, ctx| {
- workspace.open_new_file(&(), ctx);
- workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, ctx);
- assert!(workspace
- .open_entry((tree.id(), Path::new("the-new-name").into()), ctx)
- .is_none());
- });
- let editor2 = workspace.update(&mut app, |workspace, ctx| {
+ // Open a file outside of any existing worktree.
+ app.update(|ctx| {
+ workspace.update(ctx, |view, ctx| {
+ view.open_paths(&[dir2.path().join("b.txt")], ctx)
+ })
+ })
+ .await;
+ app.read(|ctx| {
+ let worktree_roots = workspace
+ .read(ctx)
+ .worktrees()
+ .iter()
+ .map(|w| w.read(ctx).abs_path())
+ .collect::<HashSet<_>>();
+ assert_eq!(
+ worktree_roots,
+ vec![dir1.path(), &dir2.path().join("b.txt")]
+ .into_iter()
+ .collect(),
+ );
+ assert_eq!(
workspace
- .active_item(ctx)
- .unwrap()
- .to_any()
- .downcast::<BufferView>()
+ .read(ctx)
+ .active_pane()
+ .read(ctx)
+ .active_item()
.unwrap()
- });
- app.read(|ctx| {
- assert_eq!(editor2.read(ctx).buffer(), editor.read(ctx).buffer());
- })
+ .title(ctx),
+ "b.txt"
+ );
});
}
- #[test]
- fn test_pane_actions() {
- App::test_async((), |mut app| async move {
- app.update(|ctx| pane::init(ctx));
-
- let dir = temp_tree(json!({
- "a": {
- "file1": "contents 1",
- "file2": "contents 2",
- "file3": "contents 3",
- },
- }));
-
- let settings = settings::channel(&app.font_cache()).unwrap().1;
- let (window_id, workspace) = app.add_window(|ctx| {
- let mut workspace = Workspace::new(0, settings, ctx);
- workspace.add_worktree(dir.path(), ctx);
- workspace
- });
- app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
- .await;
- let entries = app.read(|ctx| workspace.file_entries(ctx));
- let file1 = entries[0].clone();
+ #[gpui::test]
+ async fn test_open_and_save_new_file(mut app: gpui::TestAppContext) {
+ let dir = TempDir::new("test-new-file").unwrap();
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
+ let (_, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings, ctx);
+ workspace.add_worktree(dir.path(), ctx);
+ workspace
+ });
+ let tree = app.read(|ctx| {
+ workspace
+ .read(ctx)
+ .worktrees()
+ .iter()
+ .next()
+ .unwrap()
+ .clone()
+ });
+ tree.flush_fs_events(&app).await;
+
+ // Create a new untitled buffer
+ let editor = workspace.update(&mut app, |workspace, ctx| {
+ workspace.open_new_file(&(), ctx);
+ workspace
+ .active_item(ctx)
+ .unwrap()
+ .to_any()
+ .downcast::<BufferView>()
+ .unwrap()
+ });
+ editor.update(&mut app, |editor, ctx| {
+ assert!(!editor.is_dirty(ctx.as_ref()));
+ assert_eq!(editor.title(ctx.as_ref()), "untitled");
+ editor.insert(&"hi".to_string(), ctx);
+ assert!(editor.is_dirty(ctx.as_ref()));
+ });
+
+ // Save the buffer. This prompts for a filename.
+ workspace.update(&mut app, |workspace, ctx| {
+ workspace.save_active_item(&(), ctx)
+ });
+ app.simulate_new_path_selection(|parent_dir| {
+ assert_eq!(parent_dir, dir.path());
+ Some(parent_dir.join("the-new-name"))
+ });
+ app.read(|ctx| {
+ assert!(editor.is_dirty(ctx));
+ assert_eq!(editor.title(ctx), "untitled");
+ });
- let pane_1 = app.read(|ctx| workspace.read(ctx).active_pane().clone());
+ // When the save completes, the buffer's title is updated.
+ tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
+ .await;
+ app.read(|ctx| {
+ assert!(!editor.is_dirty(ctx));
+ assert_eq!(editor.title(ctx), "the-new-name");
+ });
+ // Edit the file and save it again. This time, there is no filename prompt.
+ editor.update(&mut app, |editor, ctx| {
+ editor.insert(&" there".to_string(), ctx);
+ assert_eq!(editor.is_dirty(ctx.as_ref()), true);
+ });
+ workspace.update(&mut app, |workspace, ctx| {
+ workspace.save_active_item(&(), ctx)
+ });
+ assert!(!app.did_prompt_for_new_path());
+ editor
+ .condition(&app, |editor, ctx| !editor.is_dirty(ctx))
+ .await;
+ app.read(|ctx| assert_eq!(editor.title(ctx), "the-new-name"));
+
+ // Open the same newly-created file in another pane item. The new editor should reuse
+ // the same buffer.
+ workspace.update(&mut app, |workspace, ctx| {
+ workspace.open_new_file(&(), ctx);
+ workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, ctx);
+ assert!(workspace
+ .open_entry((tree.id(), Path::new("the-new-name").into()), ctx)
+ .is_none());
+ });
+ let editor2 = workspace.update(&mut app, |workspace, ctx| {
workspace
- .update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx))
+ .active_item(ctx)
.unwrap()
- .await;
- app.read(|ctx| {
- assert_eq!(
- pane_1.read(ctx).active_item().unwrap().entry_id(ctx),
- Some(file1.clone())
- );
- });
+ .to_any()
+ .downcast::<BufferView>()
+ .unwrap()
+ });
+ app.read(|ctx| {
+ assert_eq!(editor2.read(ctx).buffer(), editor.read(ctx).buffer());
+ })
+ }
+
+ #[gpui::test]
+ async fn test_pane_actions(mut app: gpui::TestAppContext) {
+ app.update(|ctx| pane::init(ctx));
+
+ let dir = temp_tree(json!({
+ "a": {
+ "file1": "contents 1",
+ "file2": "contents 2",
+ "file3": "contents 3",
+ },
+ }));
+
+ let settings = settings::channel(&app.font_cache()).unwrap().1;
+ let (window_id, workspace) = app.add_window(|ctx| {
+ let mut workspace = Workspace::new(0, settings, ctx);
+ workspace.add_worktree(dir.path(), ctx);
+ workspace
+ });
+ app.read(|ctx| workspace.read(ctx).worktree_scans_complete(ctx))
+ .await;
+ let entries = app.read(|ctx| workspace.file_entries(ctx));
+ let file1 = entries[0].clone();
+
+ let pane_1 = app.read(|ctx| workspace.read(ctx).active_pane().clone());
+
+ workspace
+ .update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx))
+ .unwrap()
+ .await;
+ app.read(|ctx| {
+ assert_eq!(
+ pane_1.read(ctx).active_item().unwrap().entry_id(ctx),
+ Some(file1.clone())
+ );
+ });
- app.dispatch_action(window_id, vec![pane_1.id()], "pane:split_right", ());
- app.update(|ctx| {
- let pane_2 = workspace.read(ctx).active_pane().clone();
- assert_ne!(pane_1, pane_2);
+ app.dispatch_action(window_id, vec![pane_1.id()], "pane:split_right", ());
+ app.update(|ctx| {
+ let pane_2 = workspace.read(ctx).active_pane().clone();
+ assert_ne!(pane_1, pane_2);
- let pane2_item = pane_2.read(ctx).active_item().unwrap();
- assert_eq!(pane2_item.entry_id(ctx.as_ref()), Some(file1.clone()));
+ let pane2_item = pane_2.read(ctx).active_item().unwrap();
+ assert_eq!(pane2_item.entry_id(ctx.as_ref()), Some(file1.clone()));
- ctx.dispatch_action(window_id, vec![pane_2.id()], "pane:close_active_item", ());
- let workspace_view = workspace.read(ctx);
- assert_eq!(workspace_view.panes.len(), 1);
- assert_eq!(workspace_view.active_pane(), &pane_1);
- });
+ ctx.dispatch_action(window_id, vec![pane_2.id()], "pane:close_active_item", ());
+ let workspace_view = workspace.read(ctx);
+ assert_eq!(workspace_view.panes.len(), 1);
+ assert_eq!(workspace_view.active_pane(), &pane_1);
});
}
}
@@ -1353,7 +1353,6 @@ mod tests {
use crate::editor::Buffer;
use crate::test::*;
use anyhow::Result;
- use gpui::App;
use rand::prelude::*;
use serde_json::json;
use std::env;
@@ -1361,248 +1360,237 @@ mod tests {
use std::os::unix;
use std::time::{SystemTime, UNIX_EPOCH};
- #[test]
- fn test_populate_and_search() {
- App::test_async((), |mut app| async move {
- let dir = temp_tree(json!({
- "root": {
- "apple": "",
- "banana": {
- "carrot": {
- "date": "",
- "endive": "",
- }
- },
- "fennel": {
- "grape": "",
+ #[gpui::test]
+ async fn test_populate_and_search(mut app: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ "root": {
+ "apple": "",
+ "banana": {
+ "carrot": {
+ "date": "",
+ "endive": "",
}
+ },
+ "fennel": {
+ "grape": "",
}
- }));
+ }
+ }));
- let root_link_path = dir.path().join("root_link");
- unix::fs::symlink(&dir.path().join("root"), &root_link_path).unwrap();
- unix::fs::symlink(
- &dir.path().join("root/fennel"),
- &dir.path().join("root/finnochio"),
- )
- .unwrap();
+ let root_link_path = dir.path().join("root_link");
+ unix::fs::symlink(&dir.path().join("root"), &root_link_path).unwrap();
+ unix::fs::symlink(
+ &dir.path().join("root/fennel"),
+ &dir.path().join("root/finnochio"),
+ )
+ .unwrap();
- let tree = app.add_model(|ctx| Worktree::new(root_link_path, ctx));
+ let tree = app.add_model(|ctx| Worktree::new(root_link_path, ctx));
- app.read(|ctx| tree.read(ctx).scan_complete()).await;
- app.read(|ctx| {
- let tree = tree.read(ctx);
- assert_eq!(tree.file_count(), 5);
+ app.read(|ctx| tree.read(ctx).scan_complete()).await;
+ app.read(|ctx| {
+ let tree = tree.read(ctx);
+ assert_eq!(tree.file_count(), 5);
- assert_eq!(
- tree.inode_for_path("fennel/grape"),
- tree.inode_for_path("finnochio/grape")
- );
+ assert_eq!(
+ tree.inode_for_path("fennel/grape"),
+ tree.inode_for_path("finnochio/grape")
+ );
- let results = match_paths(
- Some(tree.snapshot()).iter(),
- "bna",
- false,
- false,
- false,
- 10,
- Default::default(),
- ctx.thread_pool().clone(),
- )
- .into_iter()
- .map(|result| result.path)
- .collect::<Vec<Arc<Path>>>();
- assert_eq!(
- results,
- vec![
- PathBuf::from("banana/carrot/date").into(),
- PathBuf::from("banana/carrot/endive").into(),
- ]
- );
- })
- });
+ let results = match_paths(
+ Some(tree.snapshot()).iter(),
+ "bna",
+ false,
+ false,
+ false,
+ 10,
+ Default::default(),
+ ctx.thread_pool().clone(),
+ )
+ .into_iter()
+ .map(|result| result.path)
+ .collect::<Vec<Arc<Path>>>();
+ assert_eq!(
+ results,
+ vec![
+ PathBuf::from("banana/carrot/date").into(),
+ PathBuf::from("banana/carrot/endive").into(),
+ ]
+ );
+ })
}
- #[test]
- fn test_save_file() {
- App::test_async((), |mut app| async move {
- let dir = temp_tree(json!({
- "file1": "the old contents",
- }));
+ #[gpui::test]
+ async fn test_save_file(mut app: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ "file1": "the old contents",
+ }));
- let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
- app.read(|ctx| tree.read(ctx).scan_complete()).await;
- app.read(|ctx| assert_eq!(tree.read(ctx).file_count(), 1));
+ let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
+ app.read(|ctx| tree.read(ctx).scan_complete()).await;
+ app.read(|ctx| assert_eq!(tree.read(ctx).file_count(), 1));
- let buffer =
- app.add_model(|ctx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), ctx));
+ let buffer =
+ app.add_model(|ctx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), ctx));
- let path = tree.update(&mut app, |tree, ctx| {
- let path = tree.files(0).next().unwrap().path().clone();
- assert_eq!(path.file_name().unwrap(), "file1");
- smol::block_on(tree.save(&path, buffer.read(ctx).snapshot(), ctx.as_ref()))
- .unwrap();
- path
- });
+ let path = tree.update(&mut app, |tree, ctx| {
+ let path = tree.files(0).next().unwrap().path().clone();
+ assert_eq!(path.file_name().unwrap(), "file1");
+ smol::block_on(tree.save(&path, buffer.read(ctx).snapshot(), ctx.as_ref())).unwrap();
+ path
+ });
- let history = app
- .read(|ctx| tree.read(ctx).load_history(&path, ctx))
- .await
- .unwrap();
- app.read(|ctx| {
- assert_eq!(history.base_text.as_ref(), buffer.read(ctx).text());
- });
+ let history = app
+ .read(|ctx| tree.read(ctx).load_history(&path, ctx))
+ .await
+ .unwrap();
+ app.read(|ctx| {
+ assert_eq!(history.base_text.as_ref(), buffer.read(ctx).text());
});
}
- #[test]
- fn test_save_in_single_file_worktree() {
- App::test_async((), |mut app| async move {
- let dir = temp_tree(json!({
- "file1": "the old contents",
- }));
-
- let tree = app.add_model(|ctx| Worktree::new(dir.path().join("file1"), ctx));
- app.read(|ctx| tree.read(ctx).scan_complete()).await;
- app.read(|ctx| assert_eq!(tree.read(ctx).file_count(), 1));
+ #[gpui::test]
+ async fn test_save_in_single_file_worktree(mut app: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ "file1": "the old contents",
+ }));
- let buffer =
- app.add_model(|ctx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), ctx));
+ let tree = app.add_model(|ctx| Worktree::new(dir.path().join("file1"), ctx));
+ app.read(|ctx| tree.read(ctx).scan_complete()).await;
+ app.read(|ctx| assert_eq!(tree.read(ctx).file_count(), 1));
- let file = app.read(|ctx| tree.file("", ctx));
- app.update(|ctx| {
- assert_eq!(file.path().file_name(), None);
- smol::block_on(file.save(buffer.read(ctx).snapshot(), ctx.as_ref())).unwrap();
- });
+ let buffer =
+ app.add_model(|ctx| Buffer::new(1, "a line of text.\n".repeat(10 * 1024), ctx));
- let history = app.read(|ctx| file.load_history(ctx)).await.unwrap();
- app.read(|ctx| assert_eq!(history.base_text.as_ref(), buffer.read(ctx).text()));
+ let file = app.read(|ctx| tree.file("", ctx));
+ app.update(|ctx| {
+ assert_eq!(file.path().file_name(), None);
+ smol::block_on(file.save(buffer.read(ctx).snapshot(), ctx.as_ref())).unwrap();
});
+
+ let history = app.read(|ctx| file.load_history(ctx)).await.unwrap();
+ app.read(|ctx| assert_eq!(history.base_text.as_ref(), buffer.read(ctx).text()));
}
- #[test]
- fn test_rescan_simple() {
- App::test_async((), |mut app| async move {
- let dir = temp_tree(json!({
- "a": {
- "file1": "",
- "file2": "",
- "file3": "",
- },
- "b": {
- "c": {
- "file4": "",
- "file5": "",
- }
+ #[gpui::test]
+ async fn test_rescan_simple(mut app: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ "a": {
+ "file1": "",
+ "file2": "",
+ "file3": "",
+ },
+ "b": {
+ "c": {
+ "file4": "",
+ "file5": "",
}
- }));
-
- let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
- let (file2, file3, file4, file5, non_existent_file) = app.read(|ctx| {
- (
- tree.file("a/file2", ctx),
- tree.file("a/file3", ctx),
- tree.file("b/c/file4", ctx),
- tree.file("b/c/file5", ctx),
- tree.file("a/filex", ctx),
- )
- });
+ }
+ }));
+
+ let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
+ let (file2, file3, file4, file5, non_existent_file) = app.read(|ctx| {
+ (
+ tree.file("a/file2", ctx),
+ tree.file("a/file3", ctx),
+ tree.file("b/c/file4", ctx),
+ tree.file("b/c/file5", ctx),
+ tree.file("a/filex", ctx),
+ )
+ });
- // The worktree hasn't scanned the directories containing these paths,
- // so it can't determine that the paths are deleted.
- assert!(!file2.is_deleted());
- assert!(!file3.is_deleted());
- assert!(!file4.is_deleted());
- assert!(!file5.is_deleted());
- assert!(!non_existent_file.is_deleted());
+ // The worktree hasn't scanned the directories containing these paths,
+ // so it can't determine that the paths are deleted.
+ assert!(!file2.is_deleted());
+ assert!(!file3.is_deleted());
+ assert!(!file4.is_deleted());
+ assert!(!file5.is_deleted());
+ assert!(!non_existent_file.is_deleted());
+
+ // After scanning, the worktree knows which files exist and which don't.
+ app.read(|ctx| tree.read(ctx).scan_complete()).await;
+ assert!(!file2.is_deleted());
+ assert!(!file3.is_deleted());
+ assert!(!file4.is_deleted());
+ assert!(!file5.is_deleted());
+ assert!(non_existent_file.is_deleted());
+
+ tree.flush_fs_events(&app).await;
+ std::fs::rename(dir.path().join("a/file3"), dir.path().join("b/c/file3")).unwrap();
+ std::fs::remove_file(dir.path().join("b/c/file5")).unwrap();
+ std::fs::rename(dir.path().join("b/c"), dir.path().join("d")).unwrap();
+ std::fs::rename(dir.path().join("a/file2"), dir.path().join("a/file2.new")).unwrap();
+ tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
+ .await;
- // After scanning, the worktree knows which files exist and which don't.
- app.read(|ctx| tree.read(ctx).scan_complete()).await;
+ app.read(|ctx| {
+ assert_eq!(
+ tree.read(ctx)
+ .paths()
+ .map(|p| p.to_str().unwrap())
+ .collect::<Vec<_>>(),
+ vec![
+ "a",
+ "a/file1",
+ "a/file2.new",
+ "b",
+ "d",
+ "d/file3",
+ "d/file4"
+ ]
+ );
+
+ assert_eq!(file2.path().to_str().unwrap(), "a/file2.new");
+ assert_eq!(file4.path().as_ref(), Path::new("d/file4"));
+ assert_eq!(file5.path().as_ref(), Path::new("d/file5"));
assert!(!file2.is_deleted());
- assert!(!file3.is_deleted());
assert!(!file4.is_deleted());
- assert!(!file5.is_deleted());
- assert!(non_existent_file.is_deleted());
-
- tree.flush_fs_events(&app).await;
- std::fs::rename(dir.path().join("a/file3"), dir.path().join("b/c/file3")).unwrap();
- std::fs::remove_file(dir.path().join("b/c/file5")).unwrap();
- std::fs::rename(dir.path().join("b/c"), dir.path().join("d")).unwrap();
- std::fs::rename(dir.path().join("a/file2"), dir.path().join("a/file2.new")).unwrap();
- tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
- .await;
-
- app.read(|ctx| {
- assert_eq!(
- tree.read(ctx)
- .paths()
- .map(|p| p.to_str().unwrap())
- .collect::<Vec<_>>(),
- vec![
- "a",
- "a/file1",
- "a/file2.new",
- "b",
- "d",
- "d/file3",
- "d/file4"
- ]
- );
+ assert!(file5.is_deleted());
- assert_eq!(file2.path().to_str().unwrap(), "a/file2.new");
- assert_eq!(file4.path().as_ref(), Path::new("d/file4"));
- assert_eq!(file5.path().as_ref(), Path::new("d/file5"));
- assert!(!file2.is_deleted());
- assert!(!file4.is_deleted());
- assert!(file5.is_deleted());
-
- // Right now, this rename isn't detected because the target path
- // no longer exists on the file system by the time we process the
- // rename event.
- assert_eq!(file3.path().as_ref(), Path::new("a/file3"));
- assert!(file3.is_deleted());
- });
+ // Right now, this rename isn't detected because the target path
+ // no longer exists on the file system by the time we process the
+ // rename event.
+ assert_eq!(file3.path().as_ref(), Path::new("a/file3"));
+ assert!(file3.is_deleted());
});
}
- #[test]
- fn test_rescan_with_gitignore() {
- App::test_async((), |mut app| async move {
- let dir = temp_tree(json!({
- ".git": {},
- ".gitignore": "ignored-dir\n",
- "tracked-dir": {
- "tracked-file1": "tracked contents",
- },
- "ignored-dir": {
- "ignored-file1": "ignored contents",
- }
- }));
-
- let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
- app.read(|ctx| tree.read(ctx).scan_complete()).await;
- tree.flush_fs_events(&app).await;
- app.read(|ctx| {
- let tree = tree.read(ctx);
- let tracked = tree.entry_for_path("tracked-dir/tracked-file1").unwrap();
- let ignored = tree.entry_for_path("ignored-dir/ignored-file1").unwrap();
- assert_eq!(tracked.is_ignored(), false);
- assert_eq!(ignored.is_ignored(), true);
- });
+ #[gpui::test]
+ async fn test_rescan_with_gitignore(mut app: gpui::TestAppContext) {
+ let dir = temp_tree(json!({
+ ".git": {},
+ ".gitignore": "ignored-dir\n",
+ "tracked-dir": {
+ "tracked-file1": "tracked contents",
+ },
+ "ignored-dir": {
+ "ignored-file1": "ignored contents",
+ }
+ }));
+
+ let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
+ app.read(|ctx| tree.read(ctx).scan_complete()).await;
+ tree.flush_fs_events(&app).await;
+ app.read(|ctx| {
+ let tree = tree.read(ctx);
+ let tracked = tree.entry_for_path("tracked-dir/tracked-file1").unwrap();
+ let ignored = tree.entry_for_path("ignored-dir/ignored-file1").unwrap();
+ assert_eq!(tracked.is_ignored(), false);
+ assert_eq!(ignored.is_ignored(), true);
+ });
- fs::write(dir.path().join("tracked-dir/tracked-file2"), "").unwrap();
- fs::write(dir.path().join("ignored-dir/ignored-file2"), "").unwrap();
- tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
- .await;
- app.read(|ctx| {
- let tree = tree.read(ctx);
- let dot_git = tree.entry_for_path(".git").unwrap();
- let tracked = tree.entry_for_path("tracked-dir/tracked-file2").unwrap();
- let ignored = tree.entry_for_path("ignored-dir/ignored-file2").unwrap();
- assert_eq!(tracked.is_ignored(), false);
- assert_eq!(ignored.is_ignored(), true);
- assert_eq!(dot_git.is_ignored(), true);
- });
+ fs::write(dir.path().join("tracked-dir/tracked-file2"), "").unwrap();
+ fs::write(dir.path().join("ignored-dir/ignored-file2"), "").unwrap();
+ tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
+ .await;
+ app.read(|ctx| {
+ let tree = tree.read(ctx);
+ let dot_git = tree.entry_for_path(".git").unwrap();
+ let tracked = tree.entry_for_path("tracked-dir/tracked-file2").unwrap();
+ let ignored = tree.entry_for_path("ignored-dir/ignored-file2").unwrap();
+ assert_eq!(tracked.is_ignored(), false);
+ assert_eq!(ignored.is_ignored(), true);
+ assert_eq!(dot_git.is_ignored(), true);
});
}