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]]
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"

View File

@ -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"] }

View File

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

View File

@ -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<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)]
pub struct Location {
pub buffer: Model<Buffer>,
@ -441,67 +432,6 @@ impl Hover {
#[derive(Default)]
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)]
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::<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::{
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<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 {
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<Output = Result<()>> {
pub fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future<Output = Result<()>> {
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<Worktree>,
pub path: Arc<Path>,
pub mtime: SystemTime,
pub(crate) entry_id: Option<ProjectEntryId>,
pub(crate) is_local: bool,
pub(crate) is_deleted: bool,
pub(crate) is_private: bool,
pub entry_id: Option<ProjectEntryId>,
pub is_local: bool,
pub is_deleted: bool,
pub is_private: bool,
}
impl language::File for File {

View File

@ -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);
});
}