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
This commit is contained in:
Piotr Osiewicz 2024-02-26 22:09:22 +01:00 committed by GitHub
parent 72009de309
commit 009384f948
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 207 additions and 98 deletions

52
Cargo.lock generated
View File

@ -3940,15 +3940,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]] [[package]]
name = "globset" name = "globset"
version = "0.4.13" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"bstr", "bstr",
"fnv",
"log", "log",
"regex", "regex-automata 0.4.5",
"regex-syntax 0.8.2",
] ]
[[package]] [[package]]
@ -4461,17 +4461,16 @@ dependencies = [
[[package]] [[package]]
name = "ignore" name = "ignore"
version = "0.4.20" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1"
dependencies = [ dependencies = [
"crossbeam-deque",
"globset", "globset",
"lazy_static",
"log", "log",
"memchr", "memchr",
"regex", "regex-automata 0.4.5",
"same-file", "same-file",
"thread_local",
"walkdir", "walkdir",
"winapi-util", "winapi-util",
] ]
@ -6835,6 +6834,7 @@ dependencies = [
"postage", "postage",
"prettier", "prettier",
"pretty_assertions", "pretty_assertions",
"project_core",
"rand 0.8.5", "rand 0.8.5",
"regex", "regex",
"release_channel", "release_channel",
@ -6855,6 +6855,40 @@ dependencies = [
"which 6.0.0", "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]] [[package]]
name = "project_panel" name = "project_panel"
version = "0.1.0" version = "0.1.0"

View File

@ -53,6 +53,7 @@ members = [
"crates/picker", "crates/picker",
"crates/prettier", "crates/prettier",
"crates/project", "crates/project",
"crates/project_core",
"crates/project_panel", "crates/project_panel",
"crates/project_symbols", "crates/project_symbols",
"crates/quick_action_bar", "crates/quick_action_bar",
@ -151,6 +152,7 @@ plugin = { path = "crates/plugin" }
plugin_macros = { path = "crates/plugin_macros" } plugin_macros = { path = "crates/plugin_macros" }
prettier = { path = "crates/prettier" } prettier = { path = "crates/prettier" }
project = { path = "crates/project" } project = { path = "crates/project" }
project_core = { path = "crates/project_core" }
project_panel = { path = "crates/project_panel" } project_panel = { path = "crates/project_panel" }
project_symbols = { path = "crates/project_symbols" } project_symbols = { path = "crates/project_symbols" }
quick_action_bar = { path = "crates/quick_action_bar" } quick_action_bar = { path = "crates/quick_action_bar" }
@ -205,6 +207,7 @@ futures = "0.3"
git2 = { version = "0.15", default-features = false } git2 = { version = "0.15", default-features = false }
globset = "0.4" globset = "0.4"
hex = "0.4.3" hex = "0.4.3"
ignore = "0.4.22"
indoc = "1" indoc = "1"
# We explicitly disable http2 support in isahc. # We explicitly disable http2 support in isahc.
isahc = { version = "1.7.2", default-features = false, features = ["static-curl", "text-decoding"] } isahc = { version = "1.7.2", default-features = false, features = ["static-curl", "text-decoding"] }

View File

@ -42,6 +42,7 @@ node_runtime.workspace = true
parking_lot.workspace = true parking_lot.workspace = true
postage.workspace = true postage.workspace = true
prettier.workspace = true prettier.workspace = true
project_core.workspace = true
rand.workspace = true rand.workspace = true
regex.workspace = true regex.workspace = true
rpc.workspace = true rpc.workspace = true
@ -71,6 +72,7 @@ release_channel.workspace = true
lsp = { workspace = true, features = ["test-support"] } lsp = { workspace = true, features = ["test-support"] }
prettier = { workspace = true, features = ["test-support"] } prettier = { workspace = true, features = ["test-support"] }
pretty_assertions.workspace = true pretty_assertions.workspace = true
project_core = { workspace = true, features = ["test-support"] }
rpc = { workspace = true, features = ["test-support"] } rpc = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] } settings = { workspace = true, features = ["test-support"] }
unindent.workspace = true unindent.workspace = true

View File

@ -1,18 +1,13 @@
pub mod debounced_delay; pub mod debounced_delay;
mod ignore;
pub mod lsp_command; pub mod lsp_command;
pub mod lsp_ext_command; pub mod lsp_ext_command;
mod prettier_support; mod prettier_support;
pub mod project_settings;
pub mod search; pub mod search;
mod task_inventory; mod task_inventory;
pub mod terminals; pub mod terminals;
pub mod worktree;
#[cfg(test)] #[cfg(test)]
mod project_tests; mod project_tests;
#[cfg(test)]
mod worktree_tests;
use anyhow::{anyhow, bail, Context as _, Result}; use anyhow::{anyhow, bail, Context as _, Result};
use client::{proto, Client, Collaborator, TypedEnvelope, UserStore}; use client::{proto, Client, Collaborator, TypedEnvelope, UserStore};
@ -57,7 +52,8 @@ use node_runtime::NodeRuntime;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use postage::watch; use postage::watch;
use prettier_support::{DefaultPrettier, PrettierInstance}; 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 rand::prelude::*;
use rpc::{ErrorCode, ErrorExt as _}; use rpc::{ErrorCode, ErrorExt as _};
@ -96,8 +92,9 @@ use util::{
pub use fs::*; pub use fs::*;
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX; 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 task_inventory::Inventory;
pub use worktree::*;
const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4; const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4;
const SERVER_REINSTALL_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1); const SERVER_REINSTALL_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
@ -318,12 +315,6 @@ pub struct ProjectPath {
pub path: Arc<Path>, pub path: Arc<Path>,
} }
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
pub struct DiagnosticSummary {
pub error_count: usize,
pub warning_count: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Location { pub struct Location {
pub buffer: Model<Buffer>, pub buffer: Model<Buffer>,
@ -441,67 +432,6 @@ impl Hover {
#[derive(Default)] #[derive(Default)]
pub struct ProjectTransaction(pub HashMap<Model<Buffer>, language::Transaction>); pub struct ProjectTransaction(pub HashMap<Model<Buffer>, language::Transaction>);
impl DiagnosticSummary {
fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FormatTrigger { pub enum FormatTrigger {
Save, Save,
@ -7105,7 +7035,7 @@ impl Project {
snapshot.repository_and_work_directory_for_path(&path)?; snapshot.repository_and_work_directory_for_path(&path)?;
let repo = snapshot.get_local_repo(&repo)?; let repo = snapshot.get_local_repo(&repo)?;
let relative_path = path.strip_prefix(&work_directory).ok()?; 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)) Some((buffer, base_text))
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()

View File

@ -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

View File

@ -0,0 +1 @@
../../LICENSE-GPL

View File

@ -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<Item = &'a DiagnosticEntry<T>>) -> 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,
}
}
}

View File

@ -1,12 +1,12 @@
use crate::{ use crate::{
copy_recursive, ignore::IgnoreStack, project_settings::ProjectSettings, DiagnosticSummary, ignore::IgnoreStack, project_settings::ProjectSettings, DiagnosticSummary, ProjectEntryId,
ProjectEntryId, RemoveOptions,
}; };
use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use ::ignore::gitignore::{Gitignore, GitignoreBuilder};
use anyhow::{anyhow, Context as _, Result}; use anyhow::{anyhow, Context as _, Result};
use client::{proto, Client}; use client::{proto, Client};
use clock::ReplicaId; use clock::ReplicaId;
use collections::{HashMap, HashSet, VecDeque}; use collections::{HashMap, HashSet, VecDeque};
use fs::{copy_recursive, RemoveOptions};
use fs::{ use fs::{
repository::{GitFileStatus, GitRepository, RepoPath}, repository::{GitFileStatus, GitRepository, RepoPath},
Fs, Fs,
@ -257,6 +257,12 @@ pub struct LocalRepositoryEntry {
pub(crate) git_dir_path: Arc<Path>, pub(crate) git_dir_path: Arc<Path>,
} }
impl LocalRepositoryEntry {
pub fn load_index_text(&self, relative_file_path: &Path) -> Option<String> {
self.repo_ptr.lock().load_index_text(relative_file_path)
}
}
impl Deref for LocalSnapshot { impl Deref for LocalSnapshot {
type Target = Snapshot; type Target = Snapshot;
@ -718,7 +724,7 @@ impl LocalWorktree {
path.starts_with(&self.abs_path) path.starts_with(&self.abs_path)
} }
pub(crate) fn load_buffer( pub fn load_buffer(
&mut self, &mut self,
id: BufferId, id: BufferId,
path: &Path, path: &Path,
@ -1593,7 +1599,7 @@ impl RemoteWorktree {
self.completed_scan_id >= scan_id self.completed_scan_id >= scan_id
} }
pub(crate) fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future<Output = Result<()>> { pub fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future<Output = Result<()>> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
if self.observed_snapshot(scan_id) { if self.observed_snapshot(scan_id) {
let _ = tx.send(()); let _ = tx.send(());
@ -1659,7 +1665,7 @@ impl RemoteWorktree {
}) })
} }
pub(crate) fn delete_entry( pub fn delete_entry(
&mut self, &mut self,
id: ProjectEntryId, id: ProjectEntryId,
scan_id: usize, scan_id: usize,
@ -2093,7 +2099,7 @@ impl Snapshot {
} }
impl LocalSnapshot { 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) self.git_repositories.get(&repo.work_directory.0)
} }
@ -2744,7 +2750,7 @@ impl WorktreeId {
Self(handle_id) Self(handle_id)
} }
pub(crate) fn from_proto(id: u64) -> Self { pub fn from_proto(id: u64) -> Self {
Self(id as usize) Self(id as usize)
} }
@ -2829,10 +2835,10 @@ pub struct File {
pub worktree: Model<Worktree>, pub worktree: Model<Worktree>,
pub path: Arc<Path>, pub path: Arc<Path>,
pub mtime: SystemTime, pub mtime: SystemTime,
pub(crate) entry_id: Option<ProjectEntryId>, pub entry_id: Option<ProjectEntryId>,
pub(crate) is_local: bool, pub is_local: bool,
pub(crate) is_deleted: bool, pub is_deleted: bool,
pub(crate) is_private: bool, pub is_private: bool,
} }
impl language::File for File { impl language::File for File {

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
project_settings::ProjectSettings, project_settings::ProjectSettings,
worktree::{Entry, EntryKind, PathChange, Worktree},
worktree::{Event, Snapshot, WorktreeModelHandle}, worktree::{Event, Snapshot, WorktreeModelHandle},
Entry, EntryKind, PathChange, Project, Worktree,
}; };
use anyhow::Result; use anyhow::Result;
use client::Client; use client::Client;
@ -14,7 +14,7 @@ use postage::stream::Stream;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use rand::prelude::*; use rand::prelude::*;
use serde_json::json; use serde_json::json;
use settings::SettingsStore; use settings::{Settings, SettingsStore};
use std::{ use std::{
env, env,
fmt::Write, fmt::Write,
@ -2535,6 +2535,6 @@ fn init_test(cx: &mut gpui::TestAppContext) {
cx.update(|cx| { cx.update(|cx| {
let settings_store = SettingsStore::test(cx); let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store); cx.set_global(settings_store);
Project::init_settings(cx); ProjectSettings::register(cx);
}); });
} }