1221 lines · 50.4 KB · Rust
RawDownload
use std::path::Path;use std::sync::Arc; use repo_metadata::entry::{DirectoryEntry, Entry, FileMetadata};use repo_metadata::file_tree_store::FileTreeState;use repo_metadata::local_model::IndexedRepoState;use repo_metadata::repositories::DetectedRepositories;use repo_metadata::watcher::DirectoryWatcher;use repo_metadata::{RepoMetadataModel, RepositoryIdentifier};use settings::Setting;use virtual_fs::{Stub, VirtualFS};use warp_core::ui::appearance::Appearance;use warpui::platform::WindowStyle;use warpui::{App, ModelHandle, SingletonEntity}; use super::FileTreeView;use crate::auth::AuthStateProvider;use crate::server::server_api::team::MockTeamClient;use crate::server::server_api::workspace::MockWorkspaceClient;use crate::settings::CodeSettings;use crate::settings_view::keybindings::KeybindingChangedNotifier;use crate::test_util::settings::initialize_settings_for_tests;use crate::vim_registers::VimRegisters;use crate::workspace::ToastStack;use crate::workspace::sync_inputs::SyncedInputState;use crate::workspaces::user_workspaces::UserWorkspaces; fn std_path(path: &std::path::Path) -> warp_util::standardized_path::StandardizedPath {    warp_util::standardized_path::StandardizedPath::try_from_local(path).unwrap()} fn initialize_app(    app: &mut App,) -> (    ModelHandle<DetectedRepositories>,    ModelHandle<RepoMetadataModel>,) {    initialize_settings_for_tests(app);     app.add_singleton_model(|_| Appearance::mock());    app.add_singleton_model(|_| ToastStack);    app.add_singleton_model(|_| SyncedInputState::mock());    app.add_singleton_model(|_| VimRegisters::new());    app.add_singleton_model(|_| KeybindingChangedNotifier::mock());    app.add_singleton_model(|_| AuthStateProvider::new_for_test());     let team_client = Arc::new(MockTeamClient::new());    let workspace_client = Arc::new(MockWorkspaceClient::new());    app.add_singleton_model(|ctx| {        UserWorkspaces::mock(team_client.clone(), workspace_client.clone(), vec![], ctx)    });     let detected_repositories = app.add_singleton_model(|_| DetectedRepositories::default());    let repository_metadata_model = app.add_singleton_model(RepoMetadataModel::new);     (detected_repositories, repository_metadata_model)} fn build_repo_state(repo_root: &std::path::Path) -> FileTreeState {    let source_file = Entry::File(FileMetadata::new(        repo_root.join("packages/app/src/main.rs"),        false,    ));    let src_dir = Entry::Directory(DirectoryEntry {        path: warp_util::standardized_path::StandardizedPath::try_from_local(            &repo_root.join("packages/app/src"),        )        .unwrap(),        children: vec![source_file],        ignored: false,        loaded: true,    });    let app_dir = Entry::Directory(DirectoryEntry {        path: warp_util::standardized_path::StandardizedPath::try_from_local(            &repo_root.join("packages/app"),        )        .unwrap(),        children: vec![src_dir],        ignored: false,        loaded: true,    });    let packages_dir = Entry::Directory(DirectoryEntry {        path: warp_util::standardized_path::StandardizedPath::try_from_local(            &repo_root.join("packages"),        )        .unwrap(),        children: vec![app_dir],        ignored: false,        loaded: true,    });    let root = Entry::Directory(DirectoryEntry {        path: std_path(repo_root),        children: vec![packages_dir],        ignored: false,        loaded: true,    });    FileTreeState::new(root, vec![], None)} fn build_repo_state_with_unloaded_directory(repo_root: &std::path::Path) -> FileTreeState {    let unloaded_src_dir = Entry::Directory(DirectoryEntry {        path: warp_util::standardized_path::StandardizedPath::try_from_local(            &repo_root.join("src"),        )        .unwrap(),        children: vec![],        ignored: false,        loaded: false,    });    let root = Entry::Directory(DirectoryEntry {        path: std_path(repo_root),        children: vec![unloaded_src_dir],        ignored: false,        loaded: true,    });    FileTreeState::new(root, vec![], None)} fn flattened_paths(    view: &FileTreeView,    root: &std::path::Path,) -> Vec<warp_util::standardized_path::StandardizedPath> {    view.root_directories        .get(&std_path(root))        .expect("root directory is tracked")        .items        .iter()        .map(|item| item.path().clone())        .collect()} async fn await_repository_indexed(    app: &mut App,    repository_metadata_model: &ModelHandle<RepoMetadataModel>,    repo_root: &Path,) {    let id = RepositoryIdentifier::local(std_path(repo_root));    let completion =        repository_metadata_model.update(app, |model, ctx| model.repository_indexed(&id, ctx));    completion.await;     repository_metadata_model.read(app, |model, ctx| {        assert!(matches!(            model.repository_state(&id, ctx),            Some(IndexedRepoState::Indexed(_))        ));    });    futures_lite::future::yield_now().await;} async fn await_directory_loaded(    app: &mut App,    repository_metadata_model: &ModelHandle<RepoMetadataModel>,    repo_root: &Path,    dir_path: &Path,) {    let repo_root = std_path(repo_root);    let dir_path = std_path(dir_path);    let completion = repository_metadata_model        .update(app, |model, ctx| {            model.load_directory_with_completion(&repo_root, &dir_path, ctx)        })        .expect("directory load should start or join an in-flight load");    completion.await.expect("directory should load");    futures_lite::future::yield_now().await;} fn set_show_hidden_files(app: &mut App, show_hidden_files: bool) {    CodeSettings::handle(app).update(app, |settings, ctx| {        Setting::set_value(&mut settings.show_hidden_files, show_hidden_files, ctx)            .expect("show hidden files setting updates");    });} #[test]fn hidden_files_are_filtered_until_setting_is_enabled() {    VirtualFS::test("file_tree_hidden_files_setting", |dirs, mut vfs| {        vfs.mkdir("tree/.config").with_files(vec![            Stub::FileWithContent("tree/.env", "SECRET=value\n"),            Stub::FileWithContent("tree/.config/settings.toml", ""),            Stub::FileWithContent("tree/visible.txt", "content\n"),        ]);        let tree = dirs.tests().join("tree");        let hidden_file = tree.join(".env");        let hidden_dir = tree.join(".config");        let visible_file = tree.join("visible.txt");         App::test((), |mut app| async move {            let (_, repository_metadata_model) = initialize_app(&mut app);            set_show_hidden_files(&mut app, false);            let (_, file_tree_view) = app.add_window(WindowStyle::NotStealFocus, FileTreeView::new);             file_tree_view.update(&mut app, |view, ctx| {                view.set_is_active(true, ctx);                view.set_root_directories(vec![tree.clone()], ctx);            });            await_repository_indexed(&mut app, &repository_metadata_model, &tree).await;             file_tree_view.read(&app, |view, _ctx| {                let paths = flattened_paths(view, &tree);                assert!(paths.contains(&std_path(&tree)));                assert!(paths.contains(&std_path(&visible_file)));                assert!(!paths.contains(&std_path(&hidden_file)));                assert!(!paths.contains(&std_path(&hidden_dir)));            });             set_show_hidden_files(&mut app, true);             file_tree_view.read(&app, |view, _ctx| {                let paths = flattened_paths(view, &tree);                assert!(paths.contains(&std_path(&hidden_file)));                assert!(paths.contains(&std_path(&hidden_dir)));            });        });    });} #[test]fn hidden_root_directory_is_not_filtered() {    VirtualFS::test("file_tree_hidden_root_directory", |dirs, mut vfs| {        vfs.mkdir(".config").with_files(vec![            Stub::FileWithContent(".config/settings.toml", ""),            Stub::FileWithContent(".config/.secret", ""),        ]);        let hidden_root = dirs.tests().join(".config");        let visible_file = hidden_root.join("settings.toml");        let hidden_file = hidden_root.join(".secret");         App::test((), |mut app| async move {            let (_, repository_metadata_model) = initialize_app(&mut app);            set_show_hidden_files(&mut app, false);            let (_, file_tree_view) = app.add_window(WindowStyle::NotStealFocus, FileTreeView::new);             file_tree_view.update(&mut app, |view, ctx| {                view.set_is_active(true, ctx);                view.set_root_directories(vec![hidden_root.clone()], ctx);            });            await_repository_indexed(&mut app, &repository_metadata_model, &hidden_root).await;             file_tree_view.read(&app, |view, _ctx| {                let paths = flattened_paths(view, &hidden_root);                assert!(paths.contains(&std_path(&hidden_root)));                assert!(paths.contains(&std_path(&visible_file)));                assert!(!paths.contains(&std_path(&hidden_file)));            });        });    });} #[test]fn selected_hidden_file_is_cleared_when_filtered() {    VirtualFS::test(        "file_tree_selected_hidden_file_filtered",        |dirs, mut vfs| {            vfs.mkdir("tree").with_files(vec![                Stub::FileWithContent("tree/.env", "SECRET=value\n"),                Stub::FileWithContent("tree/visible.txt", "content\n"),            ]);            let tree = dirs.tests().join("tree");            let hidden_file = tree.join(".env");             App::test((), |mut app| async move {                let (_, repository_metadata_model) = initialize_app(&mut app);                set_show_hidden_files(&mut app, true);                 let (_, file_tree_view) =                    app.add_window(WindowStyle::NotStealFocus, FileTreeView::new);                file_tree_view.update(&mut app, |view, ctx| {                    view.set_is_active(true, ctx);                    view.set_root_directories(vec![tree.clone()], ctx);                });                await_repository_indexed(&mut app, &repository_metadata_model, &tree).await;                 file_tree_view.update(&mut app, |view, ctx| {                    let root_dir = view.root_directories.get(&std_path(&tree)).unwrap();                    let (index, _) = root_dir                        .items                        .iter()                        .enumerate()                        .find(|(_, item)| item.path() == &std_path(&hidden_file))                        .expect("hidden file is visible");                    let id = super::FileTreeIdentifier {                        root: std_path(&tree),                        index,                    };                    view.select_id(&id, ctx);                });                 set_show_hidden_files(&mut app, false);                 file_tree_view.read(&app, |view, _ctx| {                    let paths = flattened_paths(view, &tree);                    assert!(!paths.contains(&std_path(&hidden_file)));                    assert!(view.selected_item.is_none());                });            });        },    );} #[test]fn repo_transition_unregisters_lazy_loaded_path() {    VirtualFS::test("file_tree_repo_transition", |dirs, mut vfs| {        vfs.mkdir("repo/.git/objects")            .mkdir("repo/packages/app/src")            .with_files(vec![                Stub::FileWithContent("repo/.git/HEAD", "ref: refs/heads/main"),                Stub::FileWithContent("repo/.git/config", "[core]\n\trepositoryformatversion = 0"),                Stub::FileWithContent("repo/packages/app/src/main.rs", "fn main() {}\n"),            ]);         let repo_root = dirs.tests().join("repo");        let displayed_root = repo_root.join("packages/app");        let canonical_repo_root =            warp_util::standardized_path::StandardizedPath::from_local_canonicalized(&repo_root)                .unwrap();         App::test((), |mut app| async move {            let (detected_repositories, repository_metadata_model) = initialize_app(&mut app);             let (_, file_tree_view) = app.add_window(WindowStyle::NotStealFocus, FileTreeView::new);             detected_repositories.update(&mut app, |repositories, _ctx| {                repositories.insert_test_repo_root(canonical_repo_root.clone());            });             file_tree_view.update(&mut app, |view, ctx| {                view.set_is_active(true, ctx);                view.set_root_directories(vec![displayed_root.clone()], ctx);            });             file_tree_view.read(&app, |view, _ctx| {                assert!(                    view.registered_lazy_loaded_paths.contains(                        &warp_util::standardized_path::StandardizedPath::try_from_local(                            &displayed_root                        )                        .unwrap()                    )                );                let displayed_std =                    warp_util::standardized_path::StandardizedPath::try_from_local(&displayed_root)                        .unwrap();                assert_eq!(                    view.root_directories                        .get(&displayed_std)                        .map(|root_dir| root_dir.entry.root_directory().to_local_path_lossy()),                    Some(displayed_root.clone())                );            });            repository_metadata_model.read(&app, |model, ctx| {                assert!(                    model.is_lazy_loaded_path(                        &warp_util::standardized_path::StandardizedPath::try_from_local(                            &displayed_root                        )                        .unwrap(),                        ctx                    )                );            });             repository_metadata_model.update(&mut app, |model, ctx| {                model.insert_test_state(canonical_repo_root, build_repo_state(&repo_root), ctx);            });             file_tree_view.update(&mut app, |view, ctx| {                view.set_root_directories(vec![displayed_root.clone()], ctx);            });             file_tree_view.read(&app, |view, _ctx| {                let displayed_std =                    warp_util::standardized_path::StandardizedPath::try_from_local(&displayed_root)                        .unwrap();                let repo_std =                    warp_util::standardized_path::StandardizedPath::try_from_local(&repo_root)                        .unwrap();                assert!(!view.registered_lazy_loaded_paths.contains(&displayed_std));                assert_eq!(view.root_for_path(&displayed_std), Some(repo_std.clone()));                assert_eq!(                    view.root_directories                        .get(&displayed_std)                        .map(|root_dir| (**root_dir.entry.root_directory()).clone()),                    Some(repo_std)                );            });            repository_metadata_model.read(&app, |model, ctx| {                assert!(                    !model.is_lazy_loaded_path(                        &warp_util::standardized_path::StandardizedPath::try_from_local(                            &displayed_root                        )                        .unwrap(),                        ctx                    )                );            });        });    });} #[test]fn repo_backed_unloaded_directory_loads_through_model() {    VirtualFS::test("file_tree_repo_backed_load", |dirs, mut vfs| {        vfs.mkdir("repo/.git/objects")            .mkdir("repo/src/nested")            .with_files(vec![                Stub::FileWithContent("repo/.git/HEAD", "ref: refs/heads/main"),                Stub::FileWithContent(                    "repo/.git/config",                    "[core]\trepositoryformatversion = 0",                ),                Stub::FileWithContent(                    "repo/src/nested/main.rs",                    "fn main() {}",                ),            ]);         let repo_root = dirs.tests().join("repo");        let src_dir = repo_root.join("src");        let nested_dir = repo_root.join("src/nested");        let source_file = repo_root.join("src/nested/main.rs");        let canonical_repo_root =            warp_util::standardized_path::StandardizedPath::from_local_canonicalized(&repo_root)                .unwrap();         App::test((), |mut app| async move {            let (detected_repositories, repository_metadata_model) = initialize_app(&mut app);             let (_, file_tree_view) = app.add_window(WindowStyle::NotStealFocus, FileTreeView::new);             detected_repositories.update(&mut app, |repositories, _ctx| {                repositories.insert_test_repo_root(canonical_repo_root.clone());            });            repository_metadata_model.update(&mut app, |model, ctx| {                model.insert_test_state(                    canonical_repo_root,                    build_repo_state_with_unloaded_directory(&repo_root),                    ctx,                );            });             file_tree_view.update(&mut app, |view, ctx| {                view.set_is_active(true, ctx);                view.set_root_directories(vec![repo_root.clone()], ctx);            });             file_tree_view.read(&app, |view, _ctx| {                assert!(                    !view                        .root_directories                        .get(                            &warp_util::standardized_path::StandardizedPath::try_from_local(                                &repo_root                            )                            .unwrap()                        )                        .is_some_and(|root_dir| root_dir.entry.contains(                            &warp_util::standardized_path::StandardizedPath::try_from_local(                                &source_file                            )                            .unwrap()                        ))                );            });             file_tree_view.update(&mut app, |view, ctx| {                view.ensure_loaded_path(                    &warp_util::standardized_path::StandardizedPath::try_from_local(&repo_root)                        .unwrap(),                    &warp_util::standardized_path::StandardizedPath::try_from_local(&src_dir)                        .unwrap(),                    ctx,                );            });            await_directory_loaded(&mut app, &repository_metadata_model, &repo_root, &src_dir)                .await;             file_tree_view.read(&app, |view, _ctx| {                assert!(                    view.root_directories                        .get(                            &warp_util::standardized_path::StandardizedPath::try_from_local(                                &repo_root                            )                            .unwrap()                        )                        .is_some_and(|root_dir| root_dir.entry.contains(                            &warp_util::standardized_path::StandardizedPath::try_from_local(                                &nested_dir                            )                            .unwrap()                        ))                );            });             file_tree_view.update(&mut app, |view, ctx| {                view.ensure_loaded_path(

Lines 1–500 of 1221.