Compare commits

...

3 Commits

Author SHA1 Message Date
Julia Ryan
f0e03d7b1f More migration progress 2025-12-04 15:51:26 -08:00
Julia Ryan
d3282dbc7c more progress 2025-12-01 15:38:52 -08:00
Julia Ryan
1f6a83d8d3 Include project id in settings locations 2025-11-25 22:52:59 -08:00
56 changed files with 351 additions and 229 deletions

View File

@@ -46,7 +46,7 @@ struct WorktreeDelegateAdapter(Arc<dyn LspAdapterDelegate>);
#[async_trait]
impl WorktreeDelegate for WorktreeDelegateAdapter {
fn id(&self) -> u64 {
self.0.worktree_id().to_proto()
self.0.project_worktree().worktree_id.to_proto()
}
fn root_path(&self) -> String {

View File

@@ -10,7 +10,7 @@ use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Reques
use parking_lot::Mutex;
use regex::Regex;
use release_channel::ReleaseChannel;
use settings::{Settings, SettingsStore};
use settings::{Settings, SettingsStore, WorktreeId};
use sha2::{Digest, Sha256};
use std::collections::HashSet;
use std::fs::File;
@@ -20,7 +20,7 @@ use std::time::Instant;
use std::{env, mem, path::PathBuf, sync::Arc, time::Duration};
use telemetry_events::{AssistantEventData, AssistantPhase, Event, EventRequestBody, EventWrapper};
use util::TryFutureExt;
use worktree::{UpdatedEntriesSet, WorktreeId};
use worktree::UpdatedEntriesSet;
use self::event_coalescer::EventCoalescer;
@@ -604,10 +604,11 @@ mod tests {
use clock::FakeSystemClock;
use gpui::TestAppContext;
use http_client::FakeHttpClient;
use settings::WorktreeId;
use std::collections::HashMap;
use telemetry_events::FlexibleEvent;
use util::rel_path::RelPath;
use worktree::{PathChange, ProjectEntryId, WorktreeId};
use worktree::{PathChange, ProjectEntryId};
#[gpui::test]
fn test_telemetry_flush_on_max_queue_size(cx: &mut TestAppContext) {

View File

@@ -1441,8 +1441,8 @@ mod tests {
unimplemented!()
}
fn worktree_id(&self, _: &App) -> settings::WorktreeId {
settings::WorktreeId::from_usize(0)
fn project_worktree(self, _: &App) -> settings::ProjectWorktree {
settings::ProjectWorktree::from_u64(0)
}
fn is_private(&self) -> bool {

View File

@@ -60,7 +60,7 @@ mod test_mocks {
#[async_trait::async_trait]
impl adapters::DapDelegate for MockDelegate {
fn worktree_id(&self) -> settings::WorktreeId {
settings::WorktreeId::from_usize(0)
WorktreeId(0)
}
fn worktree_root_path(&self) -> &std::path::Path {

View File

@@ -868,7 +868,7 @@ impl DebugAdapter for PythonDebugAdapter {
if let Some(found_toolchain) = delegate
.toolchain_store()
.active_toolchain(
delegate.worktree_id(),
delegate.worktree_id()
base_path.into_arc(),
language::LanguageName::new(Self::LANGUAGE_NAME),
cx,

View File

@@ -52,7 +52,7 @@ struct WorktreeDelegateAdapter(pub Arc<dyn DapDelegate>);
#[async_trait]
impl WorktreeDelegate for WorktreeDelegateAdapter {
fn id(&self) -> u64 {
self.0.worktree_id().to_proto()
self.0.worktree_id().0 as u64
}
fn root_path(&self) -> String {

View File

@@ -195,7 +195,7 @@ impl DebugPanel {
active_buffer
.as_ref()
.and_then(|buffer| buffer.read(cx).file())
.map(|f| f.worktree_id(cx))
.map(|f| f.project_worktree(cx))
});
let Some(worktree) = worktree

View File

@@ -16033,7 +16033,7 @@ impl Editor {
let (worktree_id, file) = project
.buffer_for_id(runnable.buffer, cx)
.and_then(|buffer| buffer.read(cx).file())
.map(|file| (file.worktree_id(cx), file.clone()))
.map(|file| (file.project_worktree(cx), file.clone()))
.unzip();
(
@@ -21189,7 +21189,7 @@ impl Editor {
file.is_private()
&& EditorSettings::get(
Some(SettingsLocation {
worktree_id: file.worktree_id(cx),
worktree: file.project_worktree(cx),
path: file.path().as_ref(),
}),
cx,

View File

@@ -1256,7 +1256,7 @@ impl EditorElement {
let Some(abs_path) = project.read(cx).absolute_path(
&ProjectPath {
path: file.path().clone(),
worktree_id: file.worktree_id(cx),
worktree_id: file.project_worktree(cx),
},
cx,
) else {
@@ -4157,7 +4157,7 @@ impl EditorElement {
if let Some(file) = file
&& let Some(project) = editor.read(cx).project()
&& let Some(worktree) =
project.read(cx).worktree_for_id(file.worktree_id(cx), cx)
project.read(cx).worktree_for_id(file.project_worktree(cx), cx)
{
let path_style = file.path_style(cx);
let worktree = worktree.read(cx);

View File

@@ -1281,7 +1281,7 @@ impl SerializableItem for Editor {
let buffer = self.buffer().read(cx).as_singleton()?;
let abs_path = buffer.read(cx).file().and_then(|file| {
let worktree_id = file.worktree_id(cx);
let worktree_id = file.project_worktree(cx);
project
.read(cx)
.worktree_for_id(worktree_id, cx)

View File

@@ -68,7 +68,7 @@ async fn lsp_task_context(
let worktree_abs_path = cx
.update(|cx| {
let worktree_id = buffer.read(cx).file().map(|f| f.worktree_id(cx));
let worktree_id = buffer.read(cx).file().map(|f| f.project_worktree(cx));
worktree_id
.and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx))

View File

@@ -1,6 +1,6 @@
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
use ::http_client::{AsyncBody, HttpRequestExt};
use ::settings::{Settings, WorktreeId};
use ::settings::{Settings, ProjectWorktree};
use anyhow::{Context as _, Result, bail};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
@@ -430,7 +430,7 @@ impl ExtensionImports for WasmState {
.as_ref()
.zip(location.as_ref())
.map(|(path, location)| ::settings::SettingsLocation {
worktree_id: WorktreeId::from_proto(location.worktree_id),
worktree: ProjectWorktree::from_proto(location.worktree_id),
path,
});

View File

@@ -8,7 +8,7 @@ use crate::wasm_host::wit::since_v0_6_0::{
use crate::wasm_host::wit::{CompletionKind, CompletionLabelDetails, InsertTextFormat, SymbolKind};
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
use ::http_client::{AsyncBody, HttpRequestExt};
use ::settings::{Settings, WorktreeId};
use ::settings::{Settings, ProjectWorktree};
use anyhow::{Context as _, Result, bail};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
@@ -923,7 +923,7 @@ impl ExtensionImports for WasmState {
.as_ref()
.zip(location.as_ref())
.map(|(path, location)| ::settings::SettingsLocation {
worktree_id: WorktreeId::from_proto(location.worktree_id),
worktree: ProjectWorktree::from_proto(location.worktree_id),
path,
});

View File

@@ -284,7 +284,7 @@ impl language::File for GitBlob {
self.path.file_name().unwrap()
}
fn worktree_id(&self, _: &App) -> WorktreeId {
fn project_worktree(&self, _: &App) -> WorktreeId {
self.worktree_id
}
@@ -322,7 +322,7 @@ impl language::File for CommitMetadataFile {
self.title.file_name().unwrap()
}
fn worktree_id(&self, _: &App) -> WorktreeId {
fn project_worktree(&self, _: &App) -> WorktreeId {
self.worktree_id
}

View File

@@ -3832,7 +3832,7 @@ impl GitPanel {
cx: &App,
) -> Option<AnyElement> {
let repo = self.active_repository.as_ref()?.read(cx);
let project_path = (file.worktree_id(cx), file.path().clone()).into();
let project_path = (file.project_worktree(cx), file.path().clone()).into();
let repo_path = repo.project_path_to_repo_path(&project_path, cx)?;
let ix = self.entry_by_path(&repo_path, cx)?;
let entry = self.entries.get(ix)?;

View File

@@ -349,7 +349,7 @@ impl ProjectDiff {
let file = buffer.read(cx).file()?;
Some(ProjectPath {
worktree_id: file.worktree_id(cx),
worktree_id: file.project_worktree(cx),
path: file.path().clone(),
})
}

View File

@@ -37,7 +37,7 @@ use lsp::{LanguageServerId, NumberOrString};
use parking_lot::{Mutex, RawMutex, lock_api::MutexGuard};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use settings::WorktreeId;
use settings::{ProjectWorktree, WorktreeId};
use smallvec::SmallVec;
use smol::future::yield_now;
use std::{
@@ -393,7 +393,12 @@ pub trait File: Send + Sync + Any {
/// Returns the id of the worktree to which this file belongs.
///
/// This is needed for looking up project-specific settings.
fn worktree_id(&self, cx: &App) -> WorktreeId;
fn project_worktree(&self, cx: &App) -> ProjectWorktree;
/// worktree_id
fn worktree_id(&self, cx: &App) -> WorktreeId {
self.project_worktree(cx).worktree_id
}
/// Converts this file into a protobuf message.
fn to_proto(&self, cx: &App) -> rpc::proto::File;
@@ -5422,8 +5427,8 @@ impl File for TestFile {
self.path().file_name().unwrap_or(self.root_name.as_ref())
}
fn worktree_id(&self, _: &App) -> WorktreeId {
WorktreeId::from_usize(0)
fn project_worktree(&self, _: &App) -> ProjectWorktree {
ProjectWorktree::from_u64(0)
}
fn to_proto(&self, _: &App) -> rpc::proto::File {

View File

@@ -43,7 +43,7 @@ use regex::Regex;
use schemars::{JsonSchema, SchemaGenerator, json_schema};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
use serde_json::Value;
use settings::WorktreeId;
use settings::ProjectWorktree;
use smol::future::FutureExt as _;
use std::num::NonZeroU32;
use std::{
@@ -294,7 +294,7 @@ impl CachedLspAdapter {
pub trait LspAdapterDelegate: Send + Sync {
fn show_notification(&self, message: &str, cx: &mut App);
fn http_client(&self) -> Arc<dyn HttpClient>;
fn worktree_id(&self) -> WorktreeId;
fn project_worktree(&self) -> ProjectWorktree;
fn worktree_root_path(&self) -> &Path;
fn resolve_executable_path(&self, path: PathBuf) -> PathBuf;
fn update_status(&self, language: LanguageServerName, status: BinaryStatus);

View File

@@ -26,7 +26,7 @@ pub fn language_settings<'a>(
cx: &'a App,
) -> Cow<'a, LanguageSettings> {
let location = file.map(|f| SettingsLocation {
worktree_id: f.worktree_id(cx),
worktree: f.project_worktree(cx),
path: f.path().as_ref(),
});
AllLanguageSettings::get(location, cx).language(location, language.as_ref(), cx)
@@ -38,7 +38,7 @@ pub fn all_language_settings<'a>(
cx: &'a App,
) -> &'a AllLanguageSettings {
let location = file.map(|f| SettingsLocation {
worktree_id: f.worktree_id(cx),
worktree: f.project_worktree(cx),
path: f.path().as_ref(),
});
AllLanguageSettings::get(location, cx)
@@ -435,7 +435,7 @@ impl AllLanguageSettings {
let editorconfig_properties = location.and_then(|location| {
cx.global::<SettingsStore>()
.editorconfig_properties(location.worktree_id, location.path)
.editorconfig_properties(location.worktree, location.path)
});
if let Some(editorconfig_properties) = editorconfig_properties {
let mut settings = settings.clone();

View File

@@ -1,7 +1,7 @@
use std::{borrow::Borrow, sync::Arc};
use gpui::SharedString;
use settings::WorktreeId;
use settings::ProjectWorktree;
use util::rel_path::RelPath;
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -54,6 +54,6 @@ pub trait ManifestProvider {
}
pub trait ManifestDelegate: Send + Sync {
fn worktree_id(&self) -> WorktreeId;
fn worktree_id(&self) -> ProjectWorktree;
fn exists(&self, path: &RelPath, is_dir: Option<bool>) -> bool;
}

View File

@@ -28,7 +28,7 @@ struct WorktreeDelegateAdapter(pub Arc<dyn LspAdapterDelegate>);
#[async_trait]
impl WorktreeDelegate for WorktreeDelegateAdapter {
fn id(&self) -> u64 {
self.0.worktree_id().to_proto()
self.0.project_worktree().worktree_id.to_proto()
}
fn root_path(&self) -> String {

View File

@@ -722,7 +722,7 @@ impl ContextProvider for PythonContextProvider {
let module_target = self.build_module_target(variables);
let location_file = location.file_location.buffer.read(cx).file().cloned();
let worktree_id = location_file.as_ref().map(|f| f.worktree_id(cx));
let worktree_id = location_file.as_ref().map(|f| f.project_worktree(cx));
cx.spawn(async move |cx| {
let active_toolchain = if let Some(worktree_id) = worktree_id {

View File

@@ -138,7 +138,7 @@ impl LspAdapter for YamlLspAdapter {
cx: &mut AsyncApp,
) -> Result<Value> {
let location = SettingsLocation {
worktree_id: delegate.worktree_id(),
worktree: delegate.project_worktree(),
path: RelPath::empty(),
};

View File

@@ -29,7 +29,7 @@ impl PathKey {
pub fn for_buffer(buffer: &Entity<Buffer>, cx: &App) -> Self {
if let Some(file) = buffer.read(cx).file() {
Self::with_sort_prefix(file.worktree_id(cx).to_proto(), file.path().clone())
Self::with_sort_prefix(file.worktree_id(cx).0 as u64, file.path().clone())
} else {
Self {
sort_prefix: None,

View File

@@ -2054,7 +2054,7 @@ mod extension_agent_tests {
async fn archive_agent_uses_extension_and_agent_id_for_cache_key(cx: &mut TestAppContext) {
let fs = fs::FakeFs::new(cx.background_executor.clone());
let http_client = http_client::FakeHttpClient::with_404_response();
let worktree_store = cx.new(|_| WorktreeStore::local(false, fs.clone()));
let worktree_store = cx.new(|_| WorktreeStore::local(0, false, fs.clone()));
let project_environment = cx.new(|cx| {
crate::ProjectEnvironment::new(None, worktree_store.downgrade(), None, false, cx)
});
@@ -2135,7 +2135,7 @@ mod extension_agent_tests {
let fs = fs::FakeFs::new(cx.background_executor.clone());
let http_client = http_client::FakeHttpClient::with_404_response();
let node_runtime = NodeRuntime::unavailable();
let worktree_store = cx.new(|_| WorktreeStore::local(false, fs.clone()));
let worktree_store = cx.new(|_| WorktreeStore::local(0, false, fs.clone()));
let project_environment = cx.new(|cx| {
crate::ProjectEnvironment::new(None, worktree_store.downgrade(), None, false, cx)
});
@@ -2178,7 +2178,7 @@ mod extension_agent_tests {
let fs = fs::FakeFs::new(cx.background_executor.clone());
let http_client = http_client::FakeHttpClient::with_404_response();
let node_runtime = NodeRuntime::unavailable();
let worktree_store = cx.new(|_| WorktreeStore::local(false, fs.clone()));
let worktree_store = cx.new(|_| WorktreeStore::local(0, false, fs.clone()));
let project_environment = cx.new(|cx| {
crate::ProjectEnvironment::new(None, worktree_store.downgrade(), None, false, cx)
});

View File

@@ -21,11 +21,13 @@ use rpc::{
AnyProtoClient, ErrorCode, ErrorExt as _, TypedEnvelope,
proto::{self},
};
use settings::WorktreeId;
use std::{io, sync::Arc, time::Instant};
use text::{BufferId, ReplicaId};
use util::{ResultExt as _, TryFutureExt, debug_panic, maybe, paths::PathStyle, rel_path::RelPath};
use worktree::{File, PathChange, ProjectEntryId, Worktree, WorktreeId};
use worktree::{File, PathChange, ProjectEntryId, Worktree};
/// A set of open buffers.
pub struct BufferStore {
@@ -167,7 +169,7 @@ impl RemoteBufferStore {
let buffer_result = maybe!({
let mut buffer_file = None;
if let Some(file) = state.file.take() {
let worktree_id = worktree::WorktreeId::from_proto(file.worktree_id);
let worktree_id = WorktreeId::from_proto(file.worktree_id);
let worktree = self
.worktree_store
.read(cx)

View File

@@ -529,7 +529,7 @@ impl ContextServerStore {
.visible_worktrees(cx)
.next()
.map(|worktree| settings::SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).project_worktree(),
path: RelPath::empty(),
});
&ProjectSettings::get(location, cx).context_servers

View File

@@ -32,7 +32,7 @@ use gpui::{App, AppContext, AsyncApp, Context, Entity, EventEmitter, SharedStrin
use http_client::HttpClient;
use language::{Buffer, LanguageToolchainStore};
use node_runtime::NodeRuntime;
use settings::InlayHintKind;
use settings::{InlayHintKind, WorktreeId};
use remote::RemoteClient;
use rpc::{
@@ -40,7 +40,7 @@ use rpc::{
proto::{self},
};
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsLocation, WorktreeId};
use settings::{ProjectWorktree, Settings, SettingsLocation};
use std::{
borrow::Borrow,
collections::BTreeMap,
@@ -253,7 +253,7 @@ impl DapStore {
};
let settings_location = SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).project_worktree(),
path: RelPath::empty(),
};
let dap_settings = ProjectSettings::get(Some(settings_location), cx)
@@ -855,9 +855,10 @@ impl DapStore {
let worktree = this
.update(&mut cx, |this, cx| {
this.worktree_store
.read(cx)
.worktree_for_id(WorktreeId::from_proto(envelope.payload.worktree_id), cx)
this.worktree_store.read(cx).worktree_for_id(
WorktreeId::from_proto(envelope.payload.worktree_id),
cx,
)
})?
.context("Failed to find worktree with a given ID")?;
let binary = this

View File

@@ -137,7 +137,7 @@ impl ProjectEnvironment {
None => Some({
let shell = TerminalSettings::get(
Some(settings::SettingsLocation {
worktree_id: worktree.id(),
worktree: worktree.project_worktree(),
path: RelPath::empty(),
}),
cx,
@@ -180,7 +180,7 @@ impl ProjectEnvironment {
worktree
.as_ref()
.map(|(worktree, path)| settings::SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).project_worktree(),
path: &path,
}),
cx,

View File

@@ -55,7 +55,7 @@ use rpc::{
proto::{self, git_reset, split_repository_update},
};
use serde::Deserialize;
use settings::WorktreeId;
use settings::ProjectWorktree;
use std::{
cmp::Ordering,
collections::{BTreeSet, HashSet, VecDeque},
@@ -90,7 +90,7 @@ pub struct GitStore {
buffer_store: Entity<BufferStore>,
worktree_store: Entity<WorktreeStore>,
repositories: HashMap<RepositoryId, Entity<Repository>>,
worktree_ids: HashMap<RepositoryId, HashSet<WorktreeId>>,
worktree_ids: HashMap<RepositoryId, HashSet<ProjectWorktree>>,
active_repo_id: Option<RepositoryId>,
#[allow(clippy::type_complexity)]
loading_diffs:
@@ -1166,7 +1166,7 @@ impl GitStore {
return;
}
self.update_repositories_from_worktree(
*worktree_id,
worktree_id.worktree_id,
project_environment.clone(),
next_repository_id.clone(),
downstream
@@ -1267,7 +1267,7 @@ impl GitStore {
/// Update our list of repositories and schedule git scans in response to a notification from a worktree,
fn update_repositories_from_worktree(
&mut self,
worktree_id: WorktreeId,
worktree_id: ProjectWorktree,
project_environment: Entity<ProjectEnvironment>,
next_repository_id: Arc<AtomicU64>,
updates_tx: Option<mpsc::UnboundedSender<DownstreamUpdate>>,

View File

@@ -15,8 +15,9 @@ use rpc::{AnyProtoClient, ErrorExt as _, TypedEnvelope, proto};
use std::num::NonZeroU64;
use std::path::PathBuf;
use std::sync::Arc;
use settings::WorktreeId;
use util::{ResultExt, rel_path::RelPath};
use worktree::{LoadedBinaryFile, PathChange, Worktree, WorktreeId};
use worktree::{LoadedBinaryFile, PathChange, Worktree, };
#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Ord, Eq)]
pub struct ImageId(NonZeroU64);

View File

@@ -94,7 +94,7 @@ use rpc::{
};
use serde::Serialize;
use serde_json::Value;
use settings::{Settings, SettingsLocation, SettingsStore};
use settings::{ProjectWorktree, Settings, SettingsLocation, SettingsStore, WorktreeId};
use sha2::{Digest, Sha256};
use smol::channel::Sender;
use snippet::Snippet;
@@ -134,7 +134,7 @@ pub use lsp_store::inlay_hint_cache::{CacheInlayHints, InvalidationStrategy};
pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
pub use worktree::{
Entry, EntryKind, FS_WATCH_LATENCY, File, LocalWorktree, PathChange, ProjectEntryId,
UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings,
UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeSettings,
};
const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
@@ -8427,6 +8427,10 @@ impl LspStore {
}
}
pub fn project_id_for_settings(&self, cx: &Context<Self>) -> u64 {
cx.entity_id().as_u64()
}
pub(crate) fn open_local_buffer_via_lsp(
&mut self,
abs_path: lsp::Uri,
@@ -8473,7 +8477,12 @@ impl LspStore {
let worktree = lsp_store
.update(cx, |lsp_store, cx| {
lsp_store.worktree_store.update(cx, |worktree_store, cx| {
worktree_store.create_worktree(&worktree_root_target, false, cx)
worktree_store.create_worktree(
&worktree_root_target,
self.project_id_for_settings(cx),
false,
cx,
)
})
})?
.await?;
@@ -10859,7 +10868,7 @@ impl LspStore {
for buffer in buffers {
buffer.update(cx, |buffer, cx| {
language_servers_to_stop.extend(local.language_server_ids_for_buffer(buffer, cx));
if let Some(worktree_id) = buffer.file().map(|f| f.worktree_id(cx))
if let Some(worktree_id) = buffer.file().map(|f| f.project_worktree(cx))
&& covered_worktrees.insert(worktree_id)
{
language_server_names_to_stop.retain(|name| {
@@ -13605,7 +13614,7 @@ pub fn language_server_settings<'a>(
) -> Option<&'a LspSettings> {
language_server_settings_for(
SettingsLocation {
worktree_id: delegate.worktree_id(),
worktree: delegate.project_worktree(),
path: RelPath::empty(),
},
language,
@@ -13624,6 +13633,7 @@ pub(crate) fn language_server_settings_for<'a>(
pub struct LocalLspAdapterDelegate {
lsp_store: WeakEntity<LspStore>,
worktree: worktree::Snapshot,
project_worktree: ProjectWorktree,
fs: Arc<dyn Fs>,
http_client: Arc<dyn HttpClient>,
language_registry: Arc<LanguageRegistry>,
@@ -13643,9 +13653,12 @@ impl LocalLspAdapterDelegate {
let load_shell_env_task =
environment.update(cx, |env, cx| env.worktree_environment(worktree.clone(), cx));
let project_worktree = worktree.read(cx).snapshot().project_worktree();
Arc::new(Self {
lsp_store,
worktree: worktree.read(cx).snapshot(),
project_worktree,
fs,
http_client,
language_registry,
@@ -13684,8 +13697,8 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
self.http_client.clone()
}
fn worktree_id(&self) -> WorktreeId {
self.worktree.id()
fn project_worktree(&self) -> ProjectWorktree {
self.project_worktree
}
fn worktree_root_path(&self) -> &Path {

View File

@@ -8,9 +8,8 @@ use lsp::{
MessageType, TraceValue,
};
use rpc::proto;
use settings::WorktreeId;
use crate::{LanguageServerLogType, LspStore, Project, ProjectItem as _};
use crate::{LanguageServerLogType, LspStore, Project, ProjectItem as _, WorktreeId};
const SEND_LINE: &str = "\n// Send:";
const RECEIVE_LINE: &str = "\n// Receive:";

View File

@@ -14,9 +14,10 @@ use gpui::{App, AppContext as _, Context, Entity, Subscription};
use language::{ManifestDelegate, ManifestName, ManifestQuery};
pub use manifest_store::ManifestProvidersStore;
use path_trie::{LabelPresence, RootPathTrie, TriePath};
use settings::{SettingsStore, WorktreeId};
use settings::SettingsStore;
use util::rel_path::RelPath;
use worktree::{Event as WorktreeEvent, Snapshot, Worktree};
use settings::WorktreeId;
use worktree::{Event as WorktreeEvent, Snapshot, Worktree, };
use crate::{
ProjectPath,
@@ -96,7 +97,7 @@ impl ManifestTree {
delegate: &Arc<dyn ManifestDelegate>,
cx: &mut App,
) -> Option<ProjectPath> {
debug_assert_eq!(delegate.worktree_id(), *worktree_id);
debug_assert_eq!(delegate.worktree_id().worktree_id, *worktree_id);
let (mut marked_path, mut current_presence) = (None, LabelPresence::KnownAbsent);
let worktree_roots = match self.root_points.entry(*worktree_id) {
Entry::Occupied(occupied_entry) => occupied_entry.get().clone(),
@@ -218,7 +219,7 @@ impl ManifestDelegate for ManifestQueryDelegate {
})
}
fn worktree_id(&self) -> WorktreeId {
self.worktree.id()
fn worktree_id(&self) -> settings::ProjectWorktree {
self.worktree.project_worktree()
}
}

View File

@@ -18,7 +18,7 @@ use language::{
language_settings::AllLanguageSettings,
};
use lsp::LanguageServerName;
use settings::{Settings, SettingsLocation, WorktreeId};
use settings::{WorktreeId,Settings, SettingsLocation};
use std::sync::OnceLock;
use util::rel_path::RelPath;
@@ -144,7 +144,7 @@ impl LanguageServerTree {
cx: &mut App,
) -> impl Iterator<Item = LanguageServerId> + 'a {
let manifest_location = self.manifest_location_for_path(&path, manifest_name, delegate, cx);
let adapters = self.adapters_for_language(&manifest_location, &language_name, cx);
let adapters = self.adapters_for_language(&manifest_location, &language_name, delegate, cx);
self.get_with_adapters(manifest_location, adapters)
}
@@ -158,8 +158,8 @@ impl LanguageServerTree {
cx: &'a mut App,
) -> impl Iterator<Item = LanguageServerTreeNode> + 'a {
let manifest_location = self.manifest_location_for_path(&path, manifest_name, delegate, cx);
let adapters = self.adapters_for_language(&manifest_location, &language_name, cx);
self.init_with_adapters(manifest_location, language_name, adapters, cx)
let adapters = self.adapters_for_language(&manifest_location, &language_name, delegate, cx);
self.init_with_adapters(manifest_location, language_name, adapters, delegate.clone(), cx)
}
fn init_with_adapters<'a>(
@@ -167,6 +167,7 @@ impl LanguageServerTree {
root_path: ProjectPath,
language_name: LanguageName,
adapters: IndexMap<LanguageServerName, (LspSettings, Arc<CachedLspAdapter>)>,
delegate: Arc<dyn ManifestDelegate>,
cx: &'a App,
) -> impl Iterator<Item = LanguageServerTreeNode> + 'a {
adapters.into_iter().map(move |(_, (settings, adapter))| {
@@ -181,7 +182,7 @@ impl LanguageServerTree {
.entry(adapter.name());
let (node, languages) = inner_node.or_insert_with(|| {
let toolchain = self.toolchains.read(cx).active_toolchain(
root_path.worktree_id,
delegate.worktree_id(),
&root_path.path,
language_name.clone(),
);
@@ -236,10 +237,11 @@ impl LanguageServerTree {
&self,
manifest_location: &ProjectPath,
language_name: &LanguageName,
delegate: &Arc<dyn ManifestDelegate>,
cx: &App,
) -> IndexMap<LanguageServerName, (LspSettings, Arc<CachedLspAdapter>)> {
let settings_location = SettingsLocation {
worktree_id: manifest_location.worktree_id,
worktree: delegate.worktree_id(),
path: &manifest_location.path,
};
let settings = AllLanguageSettings::get(Some(settings_location), cx).language(
@@ -401,10 +403,10 @@ impl ServerTreeRebase {
.manifest_location_for_path(&path, manifest_name, &delegate, cx);
let adapters = self
.new_tree
.adapters_for_language(&manifest, &language_name, cx);
.adapters_for_language(&manifest, &language_name, &delegate, cx);
self.new_tree
.init_with_adapters(manifest, language_name, adapters, cx)
.init_with_adapters(manifest, language_name, adapters, delegate, cx)
.filter_map(|node| {
// Inspect result of the query and initialize it ourselves before
// handing it off to the caller.

View File

@@ -22,13 +22,11 @@ use lsp::{LanguageServer, LanguageServerId, LanguageServerName};
use node_runtime::NodeRuntime;
use paths::default_prettier_dir;
use prettier::Prettier;
use settings::WorktreeId;
use smol::stream::StreamExt;
use util::{ResultExt, TryFutureExt, rel_path::RelPath};
use crate::{
File, PathChange, ProjectEntryId, Worktree, lsp_store::WorktreeId,
worktree_store::WorktreeStore,
};
use crate::{File, PathChange, ProjectEntryId, Worktree, worktree_store::WorktreeStore};
pub struct PrettierStore {
node: NodeRuntime,

View File

@@ -104,7 +104,7 @@ use rpc::{
};
use search::{SearchInputKind, SearchQuery, SearchResult};
use search_history::SearchHistory;
use settings::{InvalidSettingsError, RegisterSetting, Settings, SettingsLocation, SettingsStore};
use settings::{InvalidSettingsError, RegisterSetting, Settings, SettingsLocation, SettingsStore, WorktreeId};
use smol::channel::Receiver;
use snippet::Snippet;
pub use snippet_provider;
@@ -133,7 +133,7 @@ use util::{
use worktree::{CreatedEntry, Snapshot, Traversal};
pub use worktree::{
Entry, EntryKind, FS_WATCH_LATENCY, File, LocalWorktree, PathChange, ProjectEntryId,
UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings,
UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeSettings,
};
use worktree_store::{WorktreeStore, WorktreeStoreEvent};
@@ -367,7 +367,7 @@ pub struct ProjectPath {
impl ProjectPath {
pub fn from_file(value: &dyn language::File, cx: &App) -> Self {
ProjectPath {
worktree_id: value.worktree_id(cx),
worktree_id: value.project_worktree(cx).worktree_id,
path: value.path().clone(),
}
}
@@ -1520,6 +1520,7 @@ impl Project {
WorktreeStore::remote(
true,
client.clone().into(),
self.id,
response.payload.project_id,
path_style,
)
@@ -4227,7 +4228,7 @@ impl Project {
}
}
let buffer_worktree_id = buffer.read(cx).file().map(|file| file.worktree_id(cx));
let buffer_worktree_id = buffer.read(cx).file().map(|file| file.project_worktree(cx));
let worktrees_with_ids: Vec<_> = self
.worktrees(cx)
.map(|worktree| {
@@ -4324,7 +4325,7 @@ impl Project {
cx: &mut Context<Self>,
) -> Task<Result<Entity<Worktree>>> {
self.worktree_store.update(cx, |worktree_store, cx| {
worktree_store.create_worktree(abs_path, visible, cx)
worktree_store.create_worktree(abs_path, self.project_id_for_settings(cx), visible, cx)
})
}
@@ -5435,15 +5436,6 @@ impl<'a> Iterator for PathMatchCandidateSetIter<'a> {
impl EventEmitter<Event> for Project {}
impl<'a> From<&'a ProjectPath> for SettingsLocation<'a> {
fn from(val: &'a ProjectPath) -> Self {
SettingsLocation {
worktree_id: val.worktree_id,
path: val.path.as_ref(),
}
}
}
impl<P: Into<Arc<RelPath>>> From<(WorktreeId, P)> for ProjectPath {
fn from((worktree_id, path): (WorktreeId, P)) -> Self {
Self {
@@ -5516,7 +5508,7 @@ impl ProjectItem for Buffer {
fn project_path(&self, cx: &App) -> Option<ProjectPath> {
self.file().map(|file| ProjectPath {
worktree_id: file.worktree_id(cx),
worktree_id: file.project_worktree(cx).worktree_id.into(),
path: file.path().clone(),
})
}

View File

@@ -21,12 +21,12 @@ pub use settings::DirenvSettings;
pub use settings::LspSettings;
use settings::{
DapSettingsContent, InvalidSettingsError, LocalSettingsKind, RegisterSetting, Settings,
SettingsLocation, SettingsStore, parse_json_with_comments, watch_config_file,
SettingsLocation, SettingsStore, WorktreeId, parse_json_with_comments, watch_config_file,
};
use std::{path::PathBuf, sync::Arc, time::Duration};
use task::{DebugTaskFile, TaskTemplates, VsCodeDebugTaskFile, VsCodeTaskFile};
use util::{ResultExt, rel_path::RelPath, serde::default_true};
use worktree::{PathChange, UpdatedEntriesSet, Worktree, WorktreeId};
use worktree::{PathChange, UpdatedEntriesSet, Worktree};
use crate::{
task_store::{TaskSettingsLocation, TaskStore},
@@ -702,8 +702,8 @@ impl SettingsObserver {
let store = cx.global::<SettingsStore>();
for worktree in self.worktree_store.read(cx).worktrees() {
let worktree_id = worktree.read(cx).id().to_proto();
for (path, content) in store.local_settings(worktree.read(cx).id()) {
let worktree_id = worktree.read(cx).id();
for (path, content) in store.local_settings(worktree_id.with_project_id(project_id)) {
let content = serde_json::to_string(&content).unwrap();
downstream_client
.send(proto::UpdateWorktreeSettings {
@@ -1002,7 +1002,7 @@ impl SettingsObserver {
let result = task_store.update(cx, |task_store, cx| {
task_store.update_user_tasks(
TaskSettingsLocation::Worktree(SettingsLocation {
worktree_id,
worktree: worktree_id,
path: directory.as_ref(),
}),
file_content.as_deref(),
@@ -1031,7 +1031,7 @@ impl SettingsObserver {
let result = task_store.update(cx, |task_store, cx| {
task_store.update_user_debug_scenarios(
TaskSettingsLocation::Worktree(SettingsLocation {
worktree_id,
worktree: worktree_id,
path: directory.as_ref(),
}),
file_content.as_deref(),

View File

@@ -19,6 +19,7 @@ use language::{
};
use lsp::{LanguageServerId, LanguageServerName};
use paths::{debug_task_file_name, task_file_name};
use settings::WorktreeId;
use settings::{InvalidSettingsError, parse_json_with_comments};
use task::{
DebugScenario, ResolvedTask, TaskContext, TaskId, TaskTemplate, TaskTemplates, TaskVariables,
@@ -26,7 +27,6 @@ use task::{
};
use text::{BufferId, Point, ToPoint};
use util::{NumericPrefixWithSuffix, ResultExt as _, post_inc, rel_path::RelPath};
use worktree::WorktreeId;
use crate::{task_store::TaskSettingsLocation, worktree_store::WorktreeStore};
@@ -355,7 +355,7 @@ impl Inventory {
let buffer = buffer.read(cx);
let file = buffer.file().cloned();
(
file.as_ref().map(|file| file.worktree_id(cx)),
file.as_ref().map(|file| file.project_worktree(cx)),
file,
buffer.language().cloned(),
)
@@ -682,15 +682,16 @@ impl Inventory {
TaskSettingsLocation::Worktree(location) => {
let new_templates = new_templates.collect::<Vec<_>>();
if new_templates.is_empty() {
if let Some(worktree_tasks) =
parsed_templates.worktree.get_mut(&location.worktree_id)
if let Some(worktree_tasks) = parsed_templates
.worktree
.get_mut(&WorktreeId(location.worktree.worktree_id as usize))
{
worktree_tasks.remove(location.path);
}
} else {
parsed_templates
.worktree
.entry(location.worktree_id)
.entry(WorktreeId(location.worktree.worktree_id as usize))
.or_default()
.insert(Arc::from(location.path), new_templates);
}
@@ -701,7 +702,7 @@ impl Inventory {
..
} = kind
{
*id != location.worktree_id
id.0 != location.worktree.worktree_id as usize
|| directory_in_worktree.as_ref() != location.path
} else {
true
@@ -767,20 +768,20 @@ impl Inventory {
}
TaskSettingsLocation::Worktree(location) => {
previously_existing_scenarios = parsed_scenarios
.worktree_scenarios(location.worktree_id)
.worktree_scenarios(location.worktree)
.map(|(_, scenario)| scenario.label)
.collect::<HashSet<_>>();
if new_templates.is_empty() {
if let Some(worktree_tasks) =
parsed_scenarios.worktree.get_mut(&location.worktree_id)
parsed_scenarios.worktree.get_mut(&location.worktree)
{
worktree_tasks.remove(location.path);
}
} else {
parsed_scenarios
.worktree
.entry(location.worktree_id)
.entry(location.worktree)
.or_default()
.insert(Arc::from(location.path), new_templates);
}
@@ -848,8 +849,8 @@ fn task_variables_preference(task: &ResolvedTask) -> Reverse<usize> {
mod test_inventory {
use gpui::{AppContext as _, Entity, Task, TestAppContext};
use itertools::Itertools;
use settings::WorktreeId;
use task::TaskContext;
use worktree::WorktreeId;
use crate::Inventory;
@@ -1015,7 +1016,7 @@ impl ContextProvider for BasicContextProvider {
}
let worktree = buffer
.file()
.map(|file| file.worktree_id(cx))
.map(|file| file.project_worktree(cx))
.and_then(|worktree_id| {
self.worktree_store
.read(cx)
@@ -1181,7 +1182,7 @@ mod tests {
let worktree_id = WorktreeId::from_usize(0);
let local_worktree_location = SettingsLocation {
worktree_id,
worktree,
path: rel_path("foo"),
};
inventory.update(cx, |inventory, _| {
@@ -1397,8 +1398,8 @@ mod tests {
init_test(cx);
let inventory = cx.update(|cx| Inventory::new(cx));
let common_name = "common_task_name";
let worktree_1 = WorktreeId::from_usize(1);
let worktree_2 = WorktreeId::from_usize(2);
let worktree_1 = WorktreeId::from_usize(1).with_project_id(0);
let worktree_2 = WorktreeId::from_usize(2).with_project_id(0);
cx.run_until_parked();
let worktree_independent_tasks = vec![
@@ -1427,7 +1428,7 @@ mod tests {
let worktree_1_tasks = [
(
TaskSourceKind::Worktree {
id: worktree_1,
id: worktree_1.worktree_id,
directory_in_worktree: rel_path(".zed").into(),
id_base: "local worktree tasks from directory \".zed\"".into(),
},
@@ -1435,7 +1436,7 @@ mod tests {
),
(
TaskSourceKind::Worktree {
id: worktree_1,
id: worktree_1.worktree_id,
directory_in_worktree: rel_path(".zed").into(),
id_base: "local worktree tasks from directory \".zed\"".into(),
},
@@ -1445,7 +1446,7 @@ mod tests {
let worktree_2_tasks = [
(
TaskSourceKind::Worktree {
id: worktree_2,
id: worktree_2.worktree_id,
directory_in_worktree: rel_path(".zed").into(),
id_base: "local worktree tasks from directory \".zed\"".into(),
},
@@ -1453,7 +1454,7 @@ mod tests {
),
(
TaskSourceKind::Worktree {
id: worktree_2,
id: worktree_2.worktree_id,
directory_in_worktree: rel_path(".zed").into(),
id_base: "local worktree tasks from directory \".zed\"".into(),
},
@@ -1475,7 +1476,7 @@ mod tests {
inventory
.update_file_based_tasks(
TaskSettingsLocation::Worktree(SettingsLocation {
worktree_id: worktree_1,
worktree: worktree_1,
path: rel_path(".zed"),
}),
Some(&mock_tasks_from_names(
@@ -1486,7 +1487,7 @@ mod tests {
inventory
.update_file_based_tasks(
TaskSettingsLocation::Worktree(SettingsLocation {
worktree_id: worktree_2,
worktree: worktree_2,
path: rel_path(".zed"),
}),
Some(&mock_tasks_from_names(
@@ -1502,7 +1503,7 @@ mod tests {
"Without a worktree, only worktree-independent tasks should be listed"
);
assert_eq!(
list_tasks_sorted_by_last_used(&inventory, Some(worktree_1), cx).await,
list_tasks_sorted_by_last_used(&inventory, Some(worktree_1.worktree_id), cx).await,
worktree_1_tasks
.iter()
.chain(worktree_independent_tasks.iter())
@@ -1511,7 +1512,7 @@ mod tests {
.collect::<Vec<_>>(),
);
assert_eq!(
list_tasks_sorted_by_last_used(&inventory, Some(worktree_2), cx).await,
list_tasks_sorted_by_last_used(&inventory, Some(worktree_2.worktree_id), cx).await,
worktree_2_tasks
.iter()
.chain(worktree_independent_tasks.iter())
@@ -1526,7 +1527,7 @@ mod tests {
"Without a worktree, only worktree-independent tasks should be listed"
);
assert_eq!(
list_tasks(&inventory, Some(worktree_1), cx).await,
list_tasks(&inventory, Some(worktree_1.worktree_id), cx).await,
worktree_1_tasks
.iter()
.chain(worktree_independent_tasks.iter())
@@ -1534,7 +1535,7 @@ mod tests {
.collect::<Vec<_>>(),
);
assert_eq!(
list_tasks(&inventory, Some(worktree_2), cx).await,
list_tasks(&inventory, Some(worktree_2.worktree_id), cx).await,
worktree_2_tasks
.iter()
.chain(worktree_independent_tasks.iter())

View File

@@ -427,7 +427,7 @@ fn worktree_root(
.buffer
.read(cx)
.file()
.map(|f| f.worktree_id(cx))
.map(|f| f.project_worktree(cx))
.and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx))
.and_then(|worktree| {
let worktree = worktree.read(cx);

View File

@@ -67,7 +67,7 @@ impl Project {
&& let Some((worktree, _)) = self.find_worktree(path, cx)
{
settings_location = Some(SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).id(),
path: RelPath::empty(),
});
}
@@ -289,7 +289,7 @@ impl Project {
&& let Some((worktree, _)) = self.find_worktree(path, cx)
{
settings_location = Some(SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).id(),
path: RelPath::empty(),
});
}
@@ -464,7 +464,7 @@ impl Project {
&& let Some((worktree, _)) = self.find_worktree(path, cx)
{
settings_location = Some(SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).id(),
path: RelPath::empty(),
});
}

View File

@@ -19,7 +19,7 @@ use rpc::{
resolve_toolchain_response::Response as ResolveResponsePayload,
},
};
use settings::WorktreeId;
use settings::{ProjectWorktree, WorktreeId};
use task::Shell;
use util::{ResultExt as _, rel_path::RelPath};
@@ -297,7 +297,7 @@ impl ToolchainStore {
let toolchains = this
.update(&mut cx, |this, cx| {
let language_name = LanguageName::from_proto(envelope.payload.language_name);
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
let worktree_id = ProjectWorktree::from_proto(envelope.payload.worktree_id);
let path = RelPath::from_proto(envelope.payload.path.as_deref().unwrap_or(""))?;
anyhow::Ok(this.list_toolchains(
ProjectPath { worktree_id, path },
@@ -431,7 +431,7 @@ impl language::LanguageToolchainStore for RemoteStore {
) -> Option<Toolchain> {
self.0
.update(cx, |this, cx| {
this.active_toolchain(ProjectPath { worktree_id, path }, language_name, cx)
this.active_toolchain(ProjectPath { worktree_id: worktree_id.worktree_id, path }, language_name, cx)
})
.ok()?
.await
@@ -554,7 +554,7 @@ impl LocalToolchainStore {
}
pub(crate) fn active_toolchain(
&self,
worktree_id: WorktreeId,
worktree_id: ProjectWorktree,
relative_path: &Arc<RelPath>,
language_name: LanguageName,
) -> Option<Toolchain> {

View File

@@ -17,6 +17,7 @@ use rpc::{
AnyProtoClient, ErrorExt, TypedEnvelope,
proto::{self, REMOTE_SERVER_PROJECT_ID},
};
use settings::WorktreeId;
use smol::{
channel::{Receiver, Sender},
stream::StreamExt,
@@ -29,7 +30,7 @@ use util::{
};
use worktree::{
CreatedEntry, Entry, ProjectEntryId, UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree,
WorktreeId, WorktreeSettings,
WorktreeSettings,
};
use crate::{ProjectPath, search::SearchQuery};
@@ -52,6 +53,7 @@ enum WorktreeStoreState {
}
pub struct WorktreeStore {
project_id: u64,
next_entry_id: Arc<AtomicUsize>,
downstream_client: Option<(AnyProtoClient, u64)>,
retain_worktrees: bool,
@@ -86,8 +88,9 @@ impl WorktreeStore {
client.add_entity_request_handler(Self::handle_expand_all_for_project_entry);
}
pub fn local(retain_worktrees: bool, fs: Arc<dyn Fs>) -> Self {
pub fn local(project_id: u64, retain_worktrees: bool, fs: Arc<dyn Fs>) -> Self {
Self {
project_id,
next_entry_id: Default::default(),
loading_worktrees: Default::default(),
downstream_client: None,
@@ -101,10 +104,12 @@ impl WorktreeStore {
pub fn remote(
retain_worktrees: bool,
upstream_client: AnyProtoClient,
local_project_id: u64,
upstream_project_id: u64,
path_style: PathStyle,
) -> Self {
Self {
project_id: local_project_id,
next_entry_id: Default::default(),
loading_worktrees: Default::default(),
downstream_client: None,
@@ -197,7 +202,7 @@ impl WorktreeStore {
if let Some((tree, relative_path)) = self.find_worktree(abs_path, cx) {
Task::ready(Ok((tree, relative_path)))
} else {
let worktree = self.create_worktree(abs_path, visible, cx);
let worktree = self.create_worktree(abs_path, visible, cx);
cx.background_spawn(async move { Ok((worktree.await?, RelPath::empty().into())) })
}
}
@@ -478,12 +483,20 @@ impl WorktreeStore {
Task::ready(Err(Arc::new(anyhow!("cannot create worktrees via collab"))))
} else {
let abs_path = RemotePathBuf::new(abs_path.to_string(), *path_style);
self.create_remote_worktree(upstream_client.clone(), abs_path, visible, cx)
self.create_remote_worktree(
upstream_client.clone(),
abs_path,
visible,
cx,
)
}
}
WorktreeStoreState::Local { fs } => {
self.create_local_worktree(fs.clone(), abs_path.clone(), visible, cx)
}
WorktreeStoreState::Local { fs } => self.create_local_worktree(
fs.clone(),
abs_path.clone(),
visible,
cx,
),
};
self.loading_worktrees
@@ -527,7 +540,7 @@ impl WorktreeStore {
let path = RemotePathBuf::new(abs_path, path_style);
let response = client
.request(proto::AddWorktree {
project_id: REMOTE_SERVER_PROJECT_ID,
project_id: self.project_id,
path: path.to_proto(),
visible,
})
@@ -547,7 +560,7 @@ impl WorktreeStore {
let worktree = cx.update(|cx| {
Worktree::remote(
REMOTE_SERVER_PROJECT_ID,
self.project_id,
ReplicaId::REMOTE_SERVER,
proto::WorktreeMetadata {
id: response.worktree_id,
@@ -573,6 +586,7 @@ impl WorktreeStore {
fs: Arc<dyn Fs>,
abs_path: Arc<SanitizedPath>,
visible: bool,
project_id_for_settings: u64,
cx: &mut Context<Self>,
) -> Task<Result<Entity<Worktree>, Arc<anyhow::Error>>> {
let next_entry_id = self.next_entry_id.clone();
@@ -580,6 +594,7 @@ impl WorktreeStore {
cx.spawn(async move |this, cx| {
let worktree = Worktree::local(
SanitizedPath::cast_arc(abs_path.clone()),
project_id_for_settings,
visible,
fs,
next_entry_id,

View File

@@ -92,7 +92,7 @@ impl HeadlessProject {
languages::init(languages.clone(), fs.clone(), node_runtime.clone(), cx);
let worktree_store = cx.new(|cx| {
let mut store = WorktreeStore::local(true, fs.clone());
let mut store = WorktreeStore::local(REMOTE_SERVER_PROJECT_ID, true, fs.clone());
store.shared(REMOTE_SERVER_PROJECT_ID, session.clone(), cx);
store
});

View File

@@ -354,7 +354,7 @@ async fn test_remote_settings(cx: &mut TestAppContext, server_cx: &mut TestAppCo
assert_eq!(
AllLanguageSettings::get(
Some(SettingsLocation {
worktree_id,
worktree,
path: rel_path("src/lib.rs")
}),
cx

View File

@@ -46,8 +46,11 @@ pub struct ActiveSettingsProfileName(pub String);
impl Global for ActiveSettingsProfileName {}
/// Worktree ID within a project. Prefer [`ProjectWorktree`] when something globally unique is needed.
///
/// These are usually globally unique, but not always (particularly with remote projects).
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)]
pub struct WorktreeId(usize);
pub struct WorktreeId(pub usize);
impl From<WorktreeId> for usize {
fn from(value: WorktreeId) -> Self {
@@ -71,6 +74,32 @@ impl WorktreeId {
pub fn to_usize(self) -> usize {
self.0
}
pub fn with_project_id(self, project_id: u64) -> ProjectWorktree {
ProjectWorktree {
project_id,
worktree_id: self,
}
}
}
/// `worktree_id` and the `project_id` it belongs to.
///
/// `worktree_id` is usually globally unique, but sometimes only unique within a
/// project (e.g., when remoting).
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)]
pub struct ProjectWorktree {
pub project_id: u64,
pub worktree_id: WorktreeId,
}
impl ProjectWorktree {
#[cfg(any(test, feature = "test-support"))]
pub fn from_u64(n: u64) -> Self {
Self {
project_id: 0,
worktree_id: WorktreeId(n as usize),
}
}
}
impl fmt::Display for WorktreeId {

View File

@@ -32,7 +32,8 @@ pub type EditorconfigProperties = ec4rs::Properties;
use crate::{
ActiveSettingsProfileName, FontFamilyName, IconThemeName, LanguageSettingsContent,
LanguageToSettingsMap, ThemeName, VsCodeSettings, WorktreeId, fallible_options,
LanguageToSettingsMap, ProjectWorktree, ThemeName, VsCodeSettings,
fallible_options,
merge_from::MergeFrom,
settings_content::{
ExtensionsSettingsContent, ProjectSettingsContent, SettingsContent, UserSettingsContent,
@@ -134,7 +135,7 @@ inventory::collect!(RegisteredSetting);
#[derive(Clone, Copy, Debug)]
pub struct SettingsLocation<'a> {
pub worktree_id: WorktreeId,
pub worktree: ProjectWorktree,
pub path: &'a RelPath,
}
@@ -149,8 +150,9 @@ pub struct SettingsStore {
merged_settings: Rc<SettingsContent>,
local_settings: BTreeMap<(WorktreeId, Arc<RelPath>), SettingsContent>,
raw_editorconfig_settings: BTreeMap<(WorktreeId, Arc<RelPath>), (String, Option<Editorconfig>)>,
local_settings: BTreeMap<(ProjectWorktree, Arc<RelPath>), SettingsContent>,
raw_editorconfig_settings:
BTreeMap<(ProjectWorktree, Arc<RelPath>), (String, Option<Editorconfig>)>,
_setting_file_updates: Task<()>,
setting_file_updates_tx:
@@ -165,7 +167,7 @@ pub enum SettingsFile {
User,
Server,
/// Represents project settings in ssh projects as well as local projects
Project((WorktreeId, Arc<RelPath>)),
Project((ProjectWorktree, Arc<RelPath>)),
}
impl PartialOrd for SettingsFile {
@@ -234,7 +236,7 @@ pub struct SettingValue<T> {
#[doc(hidden)]
pub global_value: Option<T>,
#[doc(hidden)]
pub local_values: Vec<(WorktreeId, Arc<RelPath>, T)>,
pub local_values: Vec<(ProjectWorktree, Arc<RelPath>, T)>,
}
#[doc(hidden)]
@@ -244,9 +246,14 @@ pub trait AnySettingValue: 'static + Send + Sync {
fn from_settings(&self, s: &SettingsContent) -> Box<dyn Any>;
fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any;
fn all_local_values(&self) -> Vec<(WorktreeId, Arc<RelPath>, &dyn Any)>;
fn all_local_values(&self) -> Vec<(ProjectWorktree, Arc<RelPath>, &dyn Any)>;
fn set_global_value(&mut self, value: Box<dyn Any>);
fn set_local_value(&mut self, root_id: WorktreeId, path: Arc<RelPath>, value: Box<dyn Any>);
fn set_local_value(
&mut self,
root_id: ProjectWorktree,
path: Arc<RelPath>,
value: Box<dyn Any>,
);
}
/// Parameters that are used when generating some JSON schemas at runtime.
@@ -358,7 +365,7 @@ impl SettingsStore {
}
/// Get all values from project specific settings
pub fn get_all_locals<T: Settings>(&self) -> Vec<(WorktreeId, Arc<RelPath>, &T)> {
pub fn get_all_locals<T: Settings>(&self) -> Vec<(ProjectWorktree, Arc<RelPath>, &T)> {
self.setting_values
.get(&TypeId::of::<T>())
.unwrap_or_else(|| panic!("unregistered setting type {}", type_name::<T>()))
@@ -825,7 +832,7 @@ impl SettingsStore {
/// Add or remove a set of local settings via a JSON string.
pub fn set_local_settings(
&mut self,
root_id: WorktreeId,
root_id: ProjectWorktree,
directory_path: Arc<RelPath>,
kind: LocalSettingsKind,
settings_content: Option<&str>,
@@ -968,7 +975,7 @@ impl SettingsStore {
}
/// Add or remove a set of local settings via a JSON string.
pub fn clear_local_settings(&mut self, root_id: WorktreeId, cx: &mut App) -> Result<()> {
pub fn clear_local_settings(&mut self, root_id: ProjectWorktree, cx: &mut App) -> Result<()> {
self.local_settings
.retain(|(worktree_id, _), _| worktree_id != &root_id);
self.recompute_values(Some((root_id, RelPath::empty())), cx);
@@ -977,31 +984,21 @@ impl SettingsStore {
pub fn local_settings(
&self,
root_id: WorktreeId,
root_id: ProjectWorktree,
) -> impl '_ + Iterator<Item = (Arc<RelPath>, &ProjectSettingsContent)> {
self.local_settings
.range(
(root_id, RelPath::empty().into())
..(
WorktreeId::from_usize(root_id.to_usize() + 1),
RelPath::empty().into(),
),
)
.range((root_id, RelPath::empty().into())..)
.take_while(move |((project_worktree, _), _)| *project_worktree == root_id)
.map(|((_, path), content)| (path.clone(), &content.project))
}
pub fn local_editorconfig_settings(
&self,
root_id: WorktreeId,
root_id: ProjectWorktree,
) -> impl '_ + Iterator<Item = (Arc<RelPath>, String, Option<Editorconfig>)> {
self.raw_editorconfig_settings
.range(
(root_id, RelPath::empty().into())
..(
WorktreeId::from_usize(root_id.to_usize() + 1),
RelPath::empty().into(),
),
)
.range((root_id, RelPath::empty().into())..)
.take_while(move |((project_worktree, _), _)| *project_worktree == root_id)
.map(|((_, path), (content, parsed_content))| {
(path.clone(), content.clone(), parsed_content.clone())
})
@@ -1063,12 +1060,12 @@ impl SettingsStore {
fn recompute_values(
&mut self,
changed_local_path: Option<(WorktreeId, &RelPath)>,
changed_local_path: Option<(ProjectWorktree, &RelPath)>,
cx: &mut App,
) {
// Reload the global and local values for every setting.
let mut project_settings_stack = Vec::<SettingsContent>::new();
let mut paths_stack = Vec::<Option<(WorktreeId, &RelPath)>>::new();
let mut paths_stack = Vec::<Option<(ProjectWorktree, &RelPath)>>::new();
if changed_local_path.is_none() {
let mut merged = self.default_settings.as_ref().clone();
@@ -1129,7 +1126,7 @@ impl SettingsStore {
pub fn editorconfig_properties(
&self,
for_worktree: WorktreeId,
for_worktree: ProjectWorktree,
for_path: &RelPath,
) -> Option<EditorconfigProperties> {
let mut properties = EditorconfigProperties::new();
@@ -1302,7 +1299,7 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
type_name::<T>()
}
fn all_local_values(&self) -> Vec<(WorktreeId, Arc<RelPath>, &dyn Any)> {
fn all_local_values(&self) -> Vec<(ProjectWorktree, Arc<RelPath>, &dyn Any)> {
self.local_values
.iter()
.map(|(id, path, value)| (*id, path.clone(), value as _))
@@ -1310,7 +1307,11 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
}
fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any {
if let Some(SettingsLocation { worktree_id, path }) = path {
if let Some(SettingsLocation {
worktree: worktree_id,
path,
}) = path
{
for (settings_root_id, settings_path, value) in self.local_values.iter().rev() {
if worktree_id == *settings_root_id && path.starts_with(settings_path) {
return value;
@@ -1327,7 +1328,12 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
self.global_value = Some(*value.downcast().unwrap());
}
fn set_local_value(&mut self, root_id: WorktreeId, path: Arc<RelPath>, value: Box<dyn Any>) {
fn set_local_value(
&mut self,
root_id: ProjectWorktree,
path: Arc<RelPath>,
value: Box<dyn Any>,
) {
let value = *value.downcast().unwrap();
match self
.local_values
@@ -1344,7 +1350,7 @@ mod tests {
use std::num::NonZeroU32;
use crate::{
ClosePosition, ItemSettingsContent, VsCodeSettingsSource, default_settings,
ClosePosition, ItemSettingsContent, VsCodeSettingsSource, WorktreeId, default_settings,
settings_content::LanguageSettingsContent, test_settings,
};
@@ -1450,9 +1456,14 @@ mod tests {
ClosePosition::Left
);
let worktree = ProjectWorktree {
project_id: 1,
worktree_id: WorktreeId(1),
};
store
.set_local_settings(
WorktreeId::from_usize(1),
worktree,
rel_path("root1").into(),
LocalSettingsKind::Settings,
Some(r#"{ "tab_size": 5 }"#),
@@ -1461,7 +1472,7 @@ mod tests {
.unwrap();
store
.set_local_settings(
WorktreeId::from_usize(1),
worktree,
rel_path("root1/subdir").into(),
LocalSettingsKind::Settings,
Some(r#"{ "preferred_line_length": 50 }"#),
@@ -1471,7 +1482,7 @@ mod tests {
store
.set_local_settings(
WorktreeId::from_usize(1),
worktree,
rel_path("root2").into(),
LocalSettingsKind::Settings,
Some(r#"{ "tab_size": 9, "auto_update": true}"#),
@@ -1481,7 +1492,7 @@ mod tests {
assert_eq!(
store.get::<DefaultLanguageSettings>(Some(SettingsLocation {
worktree_id: WorktreeId::from_usize(1),
worktree: worktree,
path: rel_path("root1/something"),
})),
&DefaultLanguageSettings {
@@ -1491,7 +1502,7 @@ mod tests {
);
assert_eq!(
store.get::<DefaultLanguageSettings>(Some(SettingsLocation {
worktree_id: WorktreeId::from_usize(1),
worktree: worktree,
path: rel_path("root1/subdir/something"),
})),
&DefaultLanguageSettings {
@@ -1501,7 +1512,7 @@ mod tests {
);
assert_eq!(
store.get::<DefaultLanguageSettings>(Some(SettingsLocation {
worktree_id: WorktreeId::from_usize(1),
worktree,
path: rel_path("root2/something"),
})),
&DefaultLanguageSettings {
@@ -1511,7 +1522,7 @@ mod tests {
);
assert_eq!(
store.get::<AutoUpdateSetting>(Some(SettingsLocation {
worktree_id: WorktreeId::from_usize(1),
worktree,
path: rel_path("root2/something")
})),
&AutoUpdateSetting { auto_update: false }
@@ -1935,11 +1946,10 @@ mod tests {
fn test_get_value_for_field_basic(cx: &mut App) {
let mut store = SettingsStore::new(cx, &test_settings());
store.register_setting::<DefaultLanguageSettings>();
store
.set_user_settings(r#"{"preferred_line_length": 0}"#, cx)
.unwrap();
let local = (WorktreeId::from_usize(0), RelPath::empty().into_arc());
let local = (ProjectWorktree::from_u64(0), RelPath::empty().into_arc());
store
.set_local_settings(
local.0,
@@ -1999,10 +2009,10 @@ mod tests {
store.register_setting::<DefaultLanguageSettings>();
store.register_setting::<AutoUpdateSetting>();
let local_1 = (WorktreeId::from_usize(0), RelPath::empty().into_arc());
let local_1 = (ProjectWorktree::from_u64(0), RelPath::empty().into_arc());
let local_1_child = (
WorktreeId::from_usize(0),
ProjectWorktree::from_u64(0),
RelPath::new(
std::path::Path::new("child1"),
util::paths::PathStyle::Posix,
@@ -2011,9 +2021,9 @@ mod tests {
.into_arc(),
);
let local_2 = (WorktreeId::from_usize(1), RelPath::empty().into_arc());
let local_2 = (ProjectWorktree::from_u64(1), RelPath::empty().into_arc());
let local_2_child = (
WorktreeId::from_usize(1),
ProjectWorktree::from_u64(1),
RelPath::new(
std::path::Path::new("child2"),
util::paths::PathStyle::Posix,
@@ -2132,12 +2142,12 @@ mod tests {
let mut store = SettingsStore::new(cx, &test_settings());
store.register_setting::<DefaultLanguageSettings>();
let wt0_root = (WorktreeId::from_usize(0), RelPath::empty().into_arc());
let wt0_child1 = (WorktreeId::from_usize(0), rel_path("child1").into_arc());
let wt0_child2 = (WorktreeId::from_usize(0), rel_path("child2").into_arc());
let wt0_root = (ProjectWorktree::from_u64(0), RelPath::empty().into_arc());
let wt0_child1 = (ProjectWorktree::from_u64(0), rel_path("child1").into_arc());
let wt0_child2 = (ProjectWorktree::from_u64(0), rel_path("child2").into_arc());
let wt1_root = (WorktreeId::from_usize(1), RelPath::empty().into_arc());
let wt1_subdir = (WorktreeId::from_usize(1), rel_path("subdir").into_arc());
let wt1_root = (ProjectWorktree::from_u64(1), RelPath::empty().into_arc());
let wt1_subdir = (ProjectWorktree::from_u64(1), rel_path("subdir").into_arc());
fn get(content: &SettingsContent) -> &Option<u32> {
&content.project.all_languages.defaults.preferred_line_length
@@ -2232,7 +2242,7 @@ mod tests {
assert_eq!(overrides, vec![]);
let wt0_deep_child = (
WorktreeId::from_usize(0),
ProjectWorktree::from_u64(0),
rel_path("child1/subdir").into_arc(),
);
store
@@ -2255,16 +2265,16 @@ mod tests {
#[test]
fn test_file_ord() {
let wt0_root =
SettingsFile::Project((WorktreeId::from_usize(0), RelPath::empty().into_arc()));
SettingsFile::Project((ProjectWorktree::from_u64(0), RelPath::empty().into_arc()));
let wt0_child1 =
SettingsFile::Project((WorktreeId::from_usize(0), rel_path("child1").into_arc()));
SettingsFile::Project((ProjectWorktree::from_u64(0), rel_path("child1").into_arc()));
let wt0_child2 =
SettingsFile::Project((WorktreeId::from_usize(0), rel_path("child2").into_arc()));
SettingsFile::Project((ProjectWorktree::from_u64(0), rel_path("child2").into_arc()));
let wt1_root =
SettingsFile::Project((WorktreeId::from_usize(1), RelPath::empty().into_arc()));
SettingsFile::Project((ProjectWorktree::from_u64(1), RelPath::empty().into_arc()));
let wt1_subdir =
SettingsFile::Project((WorktreeId::from_usize(1), rel_path("subdir").into_arc()));
SettingsFile::Project((ProjectWorktree::from_u64(1), rel_path("subdir").into_arc()));
let mut files = vec![
&wt1_root,

View File

@@ -384,7 +384,7 @@ impl TitleBar {
let worktree_id = worktree.read(cx).id();
let settings_location = Some(SettingsLocation {
worktree_id,
worktree: worktree_id,
path: RelPath::empty(),
});

View File

@@ -452,7 +452,7 @@ impl TitleBar {
.map(|worktree| {
let worktree = worktree.read(cx);
let settings_location = SettingsLocation {
worktree_id: worktree.id(),
worktree: worktree.id(),
path: RelPath::empty(),
};

View File

@@ -83,7 +83,7 @@ impl ActiveToolchain {
let (worktree_id, path) = active_file
.update(cx, |this, cx| {
this.file().and_then(|file| {
Some((file.worktree_id(cx), file.path().parent()?.into()))
Some((file.project_worktree(cx), file.path().parent()?.into()))
})
})
.ok()
@@ -118,7 +118,7 @@ impl ActiveToolchain {
) {
let editor = editor.read(cx);
if let Some((_, buffer, _)) = editor.active_excerpt(cx)
&& let Some(worktree_id) = buffer.read(cx).file().map(|file| file.worktree_id(cx))
&& let Some(worktree_id) = buffer.read(cx).file().map(|file| file.project_worktree(cx))
{
let subscription = cx.subscribe_in(
&buffer,

View File

@@ -581,7 +581,7 @@ impl ToolchainSelector {
let project = workspace.project().clone();
let language_name = buffer.read(cx).language()?.name();
let worktree_id = buffer.read(cx).file()?.worktree_id(cx);
let worktree_id = buffer.read(cx).file()?.project_worktree(cx);
let relative_path: Arc<RelPath> = buffer.read(cx).file()?.path().parent()?.into();
let worktree_root_path = project
.read(cx)

View File

@@ -16,6 +16,7 @@ use gpui::{
SharedString, Task, WeakEntity, Window,
};
use project::{Project, ProjectEntryId, ProjectPath};
use settings::ProjectWorktree;
pub use settings::{
ActivateOnClose, ClosePosition, RegisterSetting, Settings, SettingsLocation, ShowCloseButton,
ShowDiagnostics,
@@ -592,11 +593,18 @@ impl<T: Item> ItemHandle for Entity<T> {
result
}
fn workspace_settings<'a>(&self, cx: &'a App) -> &'a WorkspaceSettings {
fn workspace_settings<'a>(
&self,
project: &Entity<Project>,
cx: &'a App,
) -> &'a WorkspaceSettings {
if let Some(project_path) = self.project_path(cx) {
WorkspaceSettings::get(
Some(SettingsLocation {
worktree_id: project_path.worktree_id,
worktree: ProjectWorktree {
worktree_id: project_path.worktree_id,
project_id: project.read(cx),
},
path: &project_path.path,
}),
cx,
@@ -805,7 +813,9 @@ impl<T: Item> ItemHandle for Entity<T> {
if item.has_deleted_file(cx)
&& !item.is_dirty(cx)
&& item.workspace_settings(cx).close_on_file_delete
&& item
.workspace_settings(&workspace.project, cx)
.close_on_file_delete
{
let item_id = item.item_id();
let close_item_task = pane.update(cx, |pane, cx| {
@@ -835,7 +845,7 @@ impl<T: Item> ItemHandle for Entity<T> {
}
ItemEvent::Edit => {
let autosave = item.workspace_settings(cx).autosave;
let autosave = item.workspace_settings(&workspace.project, cx).autosave;
if let AutosaveSetting::AfterDelay { milliseconds } = autosave {
let delay = Duration::from_millis(milliseconds.0);
@@ -867,7 +877,8 @@ impl<T: Item> ItemHandle for Entity<T> {
window,
move |workspace, window, cx| {
if let Some(item) = weak_item.upgrade()
&& item.workspace_settings(cx).autosave == AutosaveSetting::OnFocusChange
&& item.workspace_settings(&workspace.project, cx).autosave
== AutosaveSetting::OnFocusChange
{
Pane::autosave_item(&item, workspace.project.clone(), window, cx)
.detach_and_log_err(cx);

View File

@@ -4596,7 +4596,7 @@ impl Workspace {
for (i, worktree) in project.visible_worktrees(cx).enumerate() {
let name = {
let settings_location = SettingsLocation {
worktree_id: worktree.read(cx).id(),
worktree: worktree.read(cx).id(),
path: RelPath::empty(),
};

View File

@@ -38,8 +38,7 @@ use rpc::{
AnyProtoClient,
proto::{self, split_worktree_update},
};
pub use settings::WorktreeId;
use settings::{Settings, SettingsLocation, SettingsStore};
use settings::{ProjectWorktree, Settings, SettingsLocation, SettingsStore, WorktreeId};
use smallvec::{SmallVec, smallvec};
use smol::channel::{self, Sender};
use std::{
@@ -158,6 +157,7 @@ pub struct RemoteWorktree {
#[derive(Clone)]
pub struct Snapshot {
id: WorktreeId,
project_id_for_settings: u64,
/// The absolute path of the worktree root.
abs_path: Arc<SanitizedPath>,
path_style: PathStyle,
@@ -353,6 +353,7 @@ impl EventEmitter<Event> for Worktree {}
impl Worktree {
pub async fn local(
path: impl Into<Arc<Path>>,
project_id_for_settings: u64,
visible: bool,
fs: Arc<dyn Fs>,
next_entry_id: Arc<AtomicUsize>,
@@ -392,6 +393,7 @@ impl Worktree {
git_repositories: Default::default(),
snapshot: Snapshot::new(
cx.entity_id().as_u64(),
project_id_for_settings,
abs_path
.file_name()
.and_then(|f| f.to_str())
@@ -405,9 +407,8 @@ impl Worktree {
executor: cx.background_executor().clone(),
};
let worktree_id = snapshot.id();
let settings_location = Some(SettingsLocation {
worktree_id,
worktree: snapshot.project_worktree(),
path: RelPath::empty(),
});
@@ -466,7 +467,8 @@ impl Worktree {
}
pub fn remote(
project_id: u64,
remote_project_id: u64,
project_id_for_settings: u64,
replica_id: ReplicaId,
worktree: proto::WorktreeMetadata,
client: AnyProtoClient,
@@ -476,6 +478,7 @@ impl Worktree {
cx.new(|cx: &mut Context<Self>| {
let snapshot = Snapshot::new(
worktree.id,
project_id_for_settings,
RelPath::from_proto(&worktree.root_name)
.unwrap_or_else(|_| RelPath::empty().into()),
Path::new(&worktree.abs_path).into(),
@@ -492,14 +495,17 @@ impl Worktree {
let worktree_id = snapshot.id();
let settings_location = Some(SettingsLocation {
worktree_id,
worktree: settings::ProjectWorktree {
worktree_id,
project_id: project_id_for_settings,
},
path: RelPath::empty(),
});
let settings = WorktreeSettings::get(settings_location, cx).clone();
let worktree = RemoteWorktree {
client,
project_id,
project_id: remote_project_id,
replica_id,
snapshot,
file_scan_inclusions: settings.parent_dir_scan_inclusions.clone(),
@@ -611,7 +617,10 @@ impl Worktree {
pub fn settings_location(&self, _: &Context<Self>) -> SettingsLocation<'static> {
SettingsLocation {
worktree_id: self.id(),
worktree: ProjectWorktree {
project_id: self.project_id_for_settings,
worktree_id: self.id,
},
path: RelPath::empty(),
}
}
@@ -2032,12 +2041,14 @@ impl RemoteWorktree {
impl Snapshot {
pub fn new(
id: u64,
project_id_for_settings: u64,
root_name: Arc<RelPath>,
abs_path: Arc<Path>,
path_style: PathStyle,
) -> Self {
Snapshot {
id: WorktreeId::from_usize(id as usize),
project_id_for_settings,
abs_path: SanitizedPath::from_arc(abs_path),
path_style,
root_char_bag: root_name
@@ -2058,6 +2069,13 @@ impl Snapshot {
self.id
}
pub fn project_worktree(&self) -> ProjectWorktree {
ProjectWorktree {
worktree_id: self.id,
project_id: self.project_id_for_settings,
}
}
// TODO:
// Consider the following:
//
@@ -3104,8 +3122,8 @@ impl language::File for File {
.unwrap_or_else(|| self.worktree.read(cx).root_name_str())
}
fn worktree_id(&self, cx: &App) -> WorktreeId {
self.worktree.read(cx).id()
fn project_worktree(&self, cx: &App) -> ProjectWorktree {
self.worktree.read(cx).project_worktree()
}
fn to_proto(&self, cx: &App) -> rpc::proto::File {

View File

@@ -41,6 +41,7 @@ async fn test_traversal(cx: &mut TestAppContext) {
let tree = Worktree::local(
Path::new("/root"),
0,
true,
fs,
Default::default(),
@@ -105,6 +106,7 @@ async fn test_circular_symlinks(cx: &mut TestAppContext) {
let tree = Worktree::local(
Path::new("/root"),
0,
true,
fs.clone(),
Default::default(),
@@ -204,6 +206,7 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
let tree = Worktree::local(
Path::new("/root/dir1"),
0,
true,
fs.clone(),
Default::default(),
@@ -354,6 +357,7 @@ async fn test_renaming_case_only(cx: &mut TestAppContext) {
let tree = Worktree::local(
temp_root.path(),
0,
true,
fs.clone(),
Default::default(),
@@ -430,6 +434,7 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) {
let tree = Worktree::local(
Path::new("/root"),
0,
true,
fs.clone(),
Default::default(),
@@ -594,6 +599,7 @@ async fn test_dirs_no_longer_ignored(cx: &mut TestAppContext) {
let tree = Worktree::local(
Path::new("/root"),
0,
true,
fs.clone(),
Default::default(),
@@ -694,6 +700,7 @@ async fn test_write_file(cx: &mut TestAppContext) {
let worktree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -787,6 +794,7 @@ async fn test_file_scan_inclusions(cx: &mut TestAppContext) {
let tree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -852,6 +860,7 @@ async fn test_file_scan_exclusions_overrules_inclusions(cx: &mut TestAppContext)
let tree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -910,6 +919,7 @@ async fn test_file_scan_inclusions_reindexes_on_setting_change(cx: &mut TestAppC
});
let tree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -995,6 +1005,7 @@ async fn test_file_scan_exclusions(cx: &mut TestAppContext) {
let tree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -1076,6 +1087,7 @@ async fn test_hidden_files(cx: &mut TestAppContext) {
let tree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -1186,6 +1198,7 @@ async fn test_fs_events_in_exclusions(cx: &mut TestAppContext) {
let tree = Worktree::local(
dir.path(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -1297,6 +1310,7 @@ async fn test_fs_events_in_dot_git_worktree(cx: &mut TestAppContext) {
let tree = Worktree::local(
dot_git_worktree_dir.clone(),
0,
true,
Arc::new(RealFs::new(None, cx.executor())),
Default::default(),
@@ -1335,6 +1349,7 @@ async fn test_create_directory_during_initial_scan(cx: &mut TestAppContext) {
let tree = Worktree::local(
"/root".as_ref(),
0,
true,
fs,
Default::default(),
@@ -1403,6 +1418,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
let tree_fake = Worktree::local(
"/root".as_ref(),
0,
true,
fs_fake,
Default::default(),
@@ -1444,6 +1460,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
let tree_real = Worktree::local(
temp_root.path(),
0,
true,
fs_real,
Default::default(),
@@ -1555,6 +1572,7 @@ async fn test_random_worktree_operations_during_initial_scan(
let worktree = Worktree::local(
root_dir,
0,
true,
fs.clone(),
Default::default(),
@@ -1645,6 +1663,7 @@ async fn test_random_worktree_changes(cx: &mut TestAppContext, mut rng: StdRng)
let worktree = Worktree::local(
root_dir,
0,
true,
fs.clone(),
Default::default(),
@@ -1717,6 +1736,7 @@ async fn test_random_worktree_changes(cx: &mut TestAppContext, mut rng: StdRng)
{
let new_worktree = Worktree::local(
root_dir,
0,
true,
fs.clone(),
Default::default(),
@@ -2029,6 +2049,7 @@ async fn test_private_single_file_worktree(cx: &mut TestAppContext) {
.await;
let tree = Worktree::local(
Path::new("/.env"),
0,
true,
fs.clone(),
Default::default(),
@@ -2061,6 +2082,7 @@ async fn test_repository_above_root(executor: BackgroundExecutor, cx: &mut TestA
.await;
let worktree = Worktree::local(
path!("/root/subproject").as_ref(),
0,
true,
fs.clone(),
Arc::default(),
@@ -2138,6 +2160,7 @@ async fn test_global_gitignore(executor: BackgroundExecutor, cx: &mut TestAppCon
.await;
let worktree = Worktree::local(
home.join("project"),
0,
true,
fs.clone(),
Arc::default(),

View File

@@ -2357,7 +2357,7 @@ impl Zeta {
};
zeta_project
.license_detection_watchers
.get(&file.worktree_id(cx))
.get(&file.project_worktree(cx))
.as_ref()
.is_some_and(|watcher| watcher.is_project_open_source())
}