From 009384f948f35f64e60eaca98fde02ccbb53c31e Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 26 Feb 2024 22:09:22 +0100 Subject: [PATCH] Extract project_core out of project (#8438) That's done to unblock work for dynamic tasks (`task` crate has to access the worktree yet it is a dependency of a `project`). Release Notes: - N/A --- Cargo.lock | 52 +++++++++--- Cargo.toml | 3 + crates/project/Cargo.toml | 2 + crates/project/src/project.rs | 80 ++---------------- crates/project_core/Cargo.toml | 52 ++++++++++++ crates/project_core/LICENSE-GPL | 1 + .../{project => project_core}/src/ignore.rs | 0 crates/project_core/src/lib.rs | 81 +++++++++++++++++++ .../src/project_settings.rs | 0 .../{project => project_core}/src/worktree.rs | 28 ++++--- .../src/worktree_tests.rs | 6 +- 11 files changed, 207 insertions(+), 98 deletions(-) create mode 100644 crates/project_core/Cargo.toml create mode 120000 crates/project_core/LICENSE-GPL rename crates/{project => project_core}/src/ignore.rs (100%) create mode 100644 crates/project_core/src/lib.rs rename crates/{project => project_core}/src/project_settings.rs (100%) rename crates/{project => project_core}/src/worktree.rs (99%) rename crates/{project => project_core}/src/worktree_tests.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index f15a53d2d1..49a7004f00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3940,15 +3940,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", ] [[package]] @@ -4461,17 +4461,16 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata 0.4.5", "same-file", - "thread_local", "walkdir", "winapi-util", ] @@ -6835,6 +6834,7 @@ dependencies = [ "postage", "prettier", "pretty_assertions", + "project_core", "rand 0.8.5", "regex", "release_channel", @@ -6855,6 +6855,40 @@ dependencies = [ "which 6.0.0", ] +[[package]] +name = "project_core" +version = "0.1.0" +dependencies = [ + "anyhow", + "client", + "clock", + "collections", + "fs", + "futures 0.3.28", + "fuzzy", + "git", + "git2", + "gpui", + "ignore", + "itertools 0.11.0", + "language", + "log", + "lsp", + "parking_lot 0.11.2", + "postage", + "pretty_assertions", + "rand 0.8.5", + "rpc", + "schemars", + "serde", + "serde_json", + "settings", + "smol", + "sum_tree", + "text", + "util", +] + [[package]] name = "project_panel" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 78d48688ee..37a213f637 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ members = [ "crates/picker", "crates/prettier", "crates/project", + "crates/project_core", "crates/project_panel", "crates/project_symbols", "crates/quick_action_bar", @@ -151,6 +152,7 @@ plugin = { path = "crates/plugin" } plugin_macros = { path = "crates/plugin_macros" } prettier = { path = "crates/prettier" } project = { path = "crates/project" } +project_core = { path = "crates/project_core" } project_panel = { path = "crates/project_panel" } project_symbols = { path = "crates/project_symbols" } quick_action_bar = { path = "crates/quick_action_bar" } @@ -205,6 +207,7 @@ futures = "0.3" git2 = { version = "0.15", default-features = false } globset = "0.4" hex = "0.4.3" +ignore = "0.4.22" indoc = "1" # We explicitly disable http2 support in isahc. isahc = { version = "1.7.2", default-features = false, features = ["static-curl", "text-decoding"] } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index 7f91a15b18..e97fca9d67 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -42,6 +42,7 @@ node_runtime.workspace = true parking_lot.workspace = true postage.workspace = true prettier.workspace = true +project_core.workspace = true rand.workspace = true regex.workspace = true rpc.workspace = true @@ -71,6 +72,7 @@ release_channel.workspace = true lsp = { workspace = true, features = ["test-support"] } prettier = { workspace = true, features = ["test-support"] } pretty_assertions.workspace = true +project_core = { workspace = true, features = ["test-support"] } rpc = { workspace = true, features = ["test-support"] } settings = { workspace = true, features = ["test-support"] } unindent.workspace = true diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 5fb0ede9b5..c47a809b82 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1,18 +1,13 @@ pub mod debounced_delay; -mod ignore; pub mod lsp_command; pub mod lsp_ext_command; mod prettier_support; -pub mod project_settings; pub mod search; mod task_inventory; pub mod terminals; -pub mod worktree; #[cfg(test)] mod project_tests; -#[cfg(test)] -mod worktree_tests; use anyhow::{anyhow, bail, Context as _, Result}; use client::{proto, Client, Collaborator, TypedEnvelope, UserStore}; @@ -57,7 +52,8 @@ use node_runtime::NodeRuntime; use parking_lot::{Mutex, RwLock}; use postage::watch; use prettier_support::{DefaultPrettier, PrettierInstance}; -use project_settings::{LspSettings, ProjectSettings}; +use project_core::project_settings::{LspSettings, ProjectSettings}; +pub use project_core::{DiagnosticSummary, ProjectEntryId}; use rand::prelude::*; use rpc::{ErrorCode, ErrorExt as _}; @@ -96,8 +92,9 @@ use util::{ pub use fs::*; #[cfg(any(test, feature = "test-support"))] pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX; +pub use project_core::project_settings; +pub use project_core::worktree::{self, *}; pub use task_inventory::Inventory; -pub use worktree::*; const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4; const SERVER_REINSTALL_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1); @@ -318,12 +315,6 @@ pub struct ProjectPath { pub path: Arc, } -#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)] -pub struct DiagnosticSummary { - pub error_count: usize, - pub warning_count: usize, -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Location { pub buffer: Model, @@ -441,67 +432,6 @@ impl Hover { #[derive(Default)] pub struct ProjectTransaction(pub HashMap, language::Transaction>); -impl DiagnosticSummary { - fn new<'a, T: 'a>(diagnostics: impl IntoIterator>) -> Self { - let mut this = Self { - error_count: 0, - warning_count: 0, - }; - - for entry in diagnostics { - if entry.diagnostic.is_primary { - match entry.diagnostic.severity { - DiagnosticSeverity::ERROR => this.error_count += 1, - DiagnosticSeverity::WARNING => this.warning_count += 1, - _ => {} - } - } - } - - this - } - - pub fn is_empty(&self) -> bool { - self.error_count == 0 && self.warning_count == 0 - } - - pub fn to_proto( - &self, - language_server_id: LanguageServerId, - path: &Path, - ) -> proto::DiagnosticSummary { - proto::DiagnosticSummary { - path: path.to_string_lossy().to_string(), - language_server_id: language_server_id.0 as u64, - error_count: self.error_count as u32, - warning_count: self.warning_count as u32, - } - } -} - -#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct ProjectEntryId(usize); - -impl ProjectEntryId { - pub const MAX: Self = Self(usize::MAX); - - pub fn new(counter: &AtomicUsize) -> Self { - Self(counter.fetch_add(1, SeqCst)) - } - - pub fn from_proto(id: u64) -> Self { - Self(id as usize) - } - - pub fn to_proto(&self) -> u64 { - self.0 as u64 - } - - pub fn to_usize(&self) -> usize { - self.0 - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FormatTrigger { Save, @@ -7105,7 +7035,7 @@ impl Project { snapshot.repository_and_work_directory_for_path(&path)?; let repo = snapshot.get_local_repo(&repo)?; let relative_path = path.strip_prefix(&work_directory).ok()?; - let base_text = repo.repo_ptr.lock().load_index_text(relative_path); + let base_text = repo.load_index_text(relative_path); Some((buffer, base_text)) }) .collect::>() diff --git a/crates/project_core/Cargo.toml b/crates/project_core/Cargo.toml new file mode 100644 index 0000000000..c72fe909da --- /dev/null +++ b/crates/project_core/Cargo.toml @@ -0,0 +1,52 @@ +[package] +name = "project_core" +version = "0.1.0" +edition = "2021" +publish = false +license = "GPL-3.0-or-later" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +test-support = [ + "client/test-support", + "language/test-support", + "settings/test-support", + "text/test-support", + "gpui/test-support", +] + +[dependencies] +anyhow.workspace = true +client.workspace = true +clock.workspace = true +collections.workspace = true +fs.workspace = true +futures.workspace = true +fuzzy.workspace = true +git.workspace = true +gpui.workspace = true +ignore.workspace = true +itertools.workspace = true +language.workspace = true +log.workspace = true +lsp.workspace = true +parking_lot.workspace = true +postage.workspace = true +rpc.workspace = true +schemars.workspace = true +serde.workspace = true +serde_json.workspace = true +settings.workspace = true +smol.workspace = true +sum_tree.workspace = true +text.workspace = true +util.workspace = true + +[dev-dependencies] +clock = {workspace = true, features = ["test-support"]} +collections = { workspace = true, features = ["test-support"] } +git2.workspace = true +gpui = {workspace = true, features = ["test-support"]} +rand.workspace = true +settings = {workspace = true, features = ["test-support"]} +pretty_assertions.workspace = true diff --git a/crates/project_core/LICENSE-GPL b/crates/project_core/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/project_core/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/project/src/ignore.rs b/crates/project_core/src/ignore.rs similarity index 100% rename from crates/project/src/ignore.rs rename to crates/project_core/src/ignore.rs diff --git a/crates/project_core/src/lib.rs b/crates/project_core/src/lib.rs new file mode 100644 index 0000000000..ffba767a2e --- /dev/null +++ b/crates/project_core/src/lib.rs @@ -0,0 +1,81 @@ +use std::path::Path; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; + +use language::DiagnosticEntry; +use lsp::{DiagnosticSeverity, LanguageServerId}; +use rpc::proto; +use serde::Serialize; + +mod ignore; +pub mod project_settings; +pub mod worktree; +#[cfg(test)] +mod worktree_tests; + +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct ProjectEntryId(usize); + +impl ProjectEntryId { + pub const MAX: Self = Self(usize::MAX); + + pub fn new(counter: &AtomicUsize) -> Self { + Self(counter.fetch_add(1, SeqCst)) + } + + pub fn from_proto(id: u64) -> Self { + Self(id as usize) + } + + pub fn to_proto(&self) -> u64 { + self.0 as u64 + } + + pub fn to_usize(&self) -> usize { + self.0 + } +} + +#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)] +pub struct DiagnosticSummary { + pub error_count: usize, + pub warning_count: usize, +} + +impl DiagnosticSummary { + fn new<'a, T: 'a>(diagnostics: impl IntoIterator>) -> Self { + let mut this = Self { + error_count: 0, + warning_count: 0, + }; + + for entry in diagnostics { + if entry.diagnostic.is_primary { + match entry.diagnostic.severity { + DiagnosticSeverity::ERROR => this.error_count += 1, + DiagnosticSeverity::WARNING => this.warning_count += 1, + _ => {} + } + } + } + + this + } + + pub fn is_empty(&self) -> bool { + self.error_count == 0 && self.warning_count == 0 + } + + pub fn to_proto( + &self, + language_server_id: LanguageServerId, + path: &Path, + ) -> proto::DiagnosticSummary { + proto::DiagnosticSummary { + path: path.to_string_lossy().to_string(), + language_server_id: language_server_id.0 as u64, + error_count: self.error_count as u32, + warning_count: self.warning_count as u32, + } + } +} diff --git a/crates/project/src/project_settings.rs b/crates/project_core/src/project_settings.rs similarity index 100% rename from crates/project/src/project_settings.rs rename to crates/project_core/src/project_settings.rs diff --git a/crates/project/src/worktree.rs b/crates/project_core/src/worktree.rs similarity index 99% rename from crates/project/src/worktree.rs rename to crates/project_core/src/worktree.rs index e3cb5072f0..3a662fe3d0 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project_core/src/worktree.rs @@ -1,12 +1,12 @@ use crate::{ - copy_recursive, ignore::IgnoreStack, project_settings::ProjectSettings, DiagnosticSummary, - ProjectEntryId, RemoveOptions, + ignore::IgnoreStack, project_settings::ProjectSettings, DiagnosticSummary, ProjectEntryId, }; use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Context as _, Result}; use client::{proto, Client}; use clock::ReplicaId; use collections::{HashMap, HashSet, VecDeque}; +use fs::{copy_recursive, RemoveOptions}; use fs::{ repository::{GitFileStatus, GitRepository, RepoPath}, Fs, @@ -257,6 +257,12 @@ pub struct LocalRepositoryEntry { pub(crate) git_dir_path: Arc, } +impl LocalRepositoryEntry { + pub fn load_index_text(&self, relative_file_path: &Path) -> Option { + self.repo_ptr.lock().load_index_text(relative_file_path) + } +} + impl Deref for LocalSnapshot { type Target = Snapshot; @@ -718,7 +724,7 @@ impl LocalWorktree { path.starts_with(&self.abs_path) } - pub(crate) fn load_buffer( + pub fn load_buffer( &mut self, id: BufferId, path: &Path, @@ -1593,7 +1599,7 @@ impl RemoteWorktree { self.completed_scan_id >= scan_id } - pub(crate) fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future> { + pub fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future> { let (tx, rx) = oneshot::channel(); if self.observed_snapshot(scan_id) { let _ = tx.send(()); @@ -1659,7 +1665,7 @@ impl RemoteWorktree { }) } - pub(crate) fn delete_entry( + pub fn delete_entry( &mut self, id: ProjectEntryId, scan_id: usize, @@ -2093,7 +2099,7 @@ impl Snapshot { } impl LocalSnapshot { - pub(crate) fn get_local_repo(&self, repo: &RepositoryEntry) -> Option<&LocalRepositoryEntry> { + pub fn get_local_repo(&self, repo: &RepositoryEntry) -> Option<&LocalRepositoryEntry> { self.git_repositories.get(&repo.work_directory.0) } @@ -2744,7 +2750,7 @@ impl WorktreeId { Self(handle_id) } - pub(crate) fn from_proto(id: u64) -> Self { + pub fn from_proto(id: u64) -> Self { Self(id as usize) } @@ -2829,10 +2835,10 @@ pub struct File { pub worktree: Model, pub path: Arc, pub mtime: SystemTime, - pub(crate) entry_id: Option, - pub(crate) is_local: bool, - pub(crate) is_deleted: bool, - pub(crate) is_private: bool, + pub entry_id: Option, + pub is_local: bool, + pub is_deleted: bool, + pub is_private: bool, } impl language::File for File { diff --git a/crates/project/src/worktree_tests.rs b/crates/project_core/src/worktree_tests.rs similarity index 99% rename from crates/project/src/worktree_tests.rs rename to crates/project_core/src/worktree_tests.rs index 1ee7e2cdab..d5391d4205 100644 --- a/crates/project/src/worktree_tests.rs +++ b/crates/project_core/src/worktree_tests.rs @@ -1,7 +1,7 @@ use crate::{ project_settings::ProjectSettings, + worktree::{Entry, EntryKind, PathChange, Worktree}, worktree::{Event, Snapshot, WorktreeModelHandle}, - Entry, EntryKind, PathChange, Project, Worktree, }; use anyhow::Result; use client::Client; @@ -14,7 +14,7 @@ use postage::stream::Stream; use pretty_assertions::assert_eq; use rand::prelude::*; use serde_json::json; -use settings::SettingsStore; +use settings::{Settings, SettingsStore}; use std::{ env, fmt::Write, @@ -2535,6 +2535,6 @@ fn init_test(cx: &mut gpui::TestAppContext) { cx.update(|cx| { let settings_store = SettingsStore::test(cx); cx.set_global(settings_store); - Project::init_settings(cx); + ProjectSettings::register(cx); }); }