More migration progress

This commit is contained in:
Julia Ryan
2025-12-04 15:51:26 -08:00
parent d3282dbc7c
commit f0e03d7b1f
33 changed files with 201 additions and 161 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

@@ -12,7 +12,7 @@ use language::{LanguageName, LanguageToolchainStore};
use node_runtime::NodeRuntime;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::ProjectWorktree;
use settings::WorktreeId;
use smol::fs::File;
use std::{
borrow::Borrow,
@@ -36,7 +36,7 @@ pub enum DapStatus {
#[async_trait]
pub trait DapDelegate: Send + Sync + 'static {
fn worktree_id(&self) -> ProjectWorktree;
fn worktree_id(&self) -> WorktreeId;
fn worktree_root_path(&self) -> &Path;
fn http_client(&self) -> Arc<dyn HttpClient>;
fn node_runtime(&self) -> NodeRuntime;

View File

@@ -59,8 +59,8 @@ mod test_mocks {
#[async_trait::async_trait]
impl adapters::DapDelegate for MockDelegate {
fn worktree_id(&self) -> settings::ProjectWorktree {
settings::ProjectWorktree::from_u64(0)
fn worktree_id(&self) -> settings::WorktreeId {
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().worktree_id
self.0.worktree_id().0 as u64
}
fn root_path(&self) -> String {

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::ProjectWorktree;
use settings::{ProjectWorktree, WorktreeId};
use smallvec::SmallVec;
use smol::future::yield_now;
use std::{
@@ -396,7 +396,7 @@ pub trait File: Send + Sync + Any {
fn project_worktree(&self, cx: &App) -> ProjectWorktree;
/// worktree_id
fn worktree_id(&self, cx: &App) -> u64 {
fn worktree_id(&self, cx: &App) -> WorktreeId {
self.project_worktree(cx).worktree_id
}

View File

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

@@ -10,7 +10,7 @@ use async_trait::async_trait;
use collections::HashMap;
use fs::Fs;
use gpui::{App, AsyncApp, SharedString};
use settings::ProjectWorktree;
use settings::WorktreeId;
use task::ShellKind;
use util::rel_path::RelPath;
@@ -36,7 +36,7 @@ pub struct Toolchain {
/// - Only in the subproject they're currently in.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum ToolchainScope {
Subproject(ProjectWorktree, Arc<RelPath>),
Subproject(WorktreeId, Arc<RelPath>),
Project,
/// Available in all projects on this box. It wouldn't make sense to show suggestions across machines.
Global,
@@ -130,7 +130,7 @@ pub struct ToolchainMetadata {
pub trait LanguageToolchainStore: Send + Sync + 'static {
async fn active_toolchain(
self: Arc<Self>,
worktree_id: ProjectWorktree,
worktree_id: WorktreeId,
relative_path: Arc<RelPath>,
language_name: LanguageName,
cx: &mut AsyncApp,
@@ -140,7 +140,7 @@ pub trait LanguageToolchainStore: Send + Sync + 'static {
pub trait LocalLanguageToolchainStore: Send + Sync + 'static {
fn active_toolchain(
self: Arc<Self>,
worktree_id: ProjectWorktree,
worktree_id: WorktreeId,
relative_path: &Arc<RelPath>,
language_name: LanguageName,
cx: &mut AsyncApp,
@@ -151,7 +151,7 @@ pub trait LocalLanguageToolchainStore: Send + Sync + 'static {
impl<T: LocalLanguageToolchainStore> LanguageToolchainStore for T {
async fn active_toolchain(
self: Arc<Self>,
worktree_id: ProjectWorktree,
worktree_id: WorktreeId,
relative_path: Arc<RelPath>,
language_name: LanguageName,
cx: &mut AsyncApp,

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

@@ -138,7 +138,7 @@ impl LspAdapter for YamlLspAdapter {
cx: &mut AsyncApp,
) -> Result<Value> {
let location = SettingsLocation {
worktree: 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.project_worktree(cx).worktree_id as u64, 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)
@@ -906,7 +908,7 @@ impl BufferStore {
this.update(cx, |this, cx| {
old_file.clone().and_then(|file| {
this.path_to_buffer_id.remove(&ProjectPath {
worktree_id: file.project_worktree(cx).into(),
worktree_id: file.worktree_id(cx),
path: file.path().clone(),
})
});

View File

@@ -529,7 +529,7 @@ impl ContextServerStore {
.visible_worktrees(cx)
.next()
.map(|worktree| settings::SettingsLocation {
worktree: 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, ProjectWorktree};
use settings::{ProjectWorktree, Settings, SettingsLocation};
use std::{
borrow::Borrow,
collections::BTreeMap,
@@ -253,7 +253,7 @@ impl DapStore {
};
let settings_location = SettingsLocation {
worktree: 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(ProjectWorktree::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
@@ -971,7 +972,7 @@ impl DapAdapterDelegate {
#[async_trait]
impl dap::adapters::DapDelegate for DapAdapterDelegate {
fn worktree_id(&self) -> ProjectWorktree {
fn worktree_id(&self) -> WorktreeId {
self.worktree.id()
}

View File

@@ -180,7 +180,7 @@ impl ProjectEnvironment {
worktree
.as_ref()
.map(|(worktree, path)| settings::SettingsLocation {
worktree: worktree.read(cx).id(),
worktree: worktree.read(cx).project_worktree(),
path: &path,
}),
cx,

View File

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

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);
@@ -8477,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, self.project_id_for_settings(cx), false, cx)
worktree_store.create_worktree(
&worktree_root_target,
self.project_id_for_settings(cx),
false,
cx,
)
})
})?
.await?;
@@ -13609,7 +13614,7 @@ pub fn language_server_settings<'a>(
) -> Option<&'a LspSettings> {
language_server_settings_for(
SettingsLocation {
worktree: delegate.worktree_id(),
worktree: delegate.project_worktree(),
path: RelPath::empty(),
},
language,
@@ -13628,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>,
@@ -13647,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,
@@ -13688,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,7 +8,6 @@ use lsp::{
MessageType, TraceValue,
};
use rpc::proto;
use settings::ProjectWorktree;
use crate::{LanguageServerLogType, LspStore, Project, ProjectItem as _, WorktreeId};

View File

@@ -16,7 +16,8 @@ pub use manifest_store::ManifestProvidersStore;
use path_trie::{LabelPresence, RootPathTrie, TriePath};
use settings::SettingsStore;
use util::rel_path::RelPath;
use worktree::{Event as WorktreeEvent, Snapshot, Worktree, WorktreeId};
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, worktree_id.to_usize() as u64);
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(),

View File

@@ -18,8 +18,7 @@ use language::{
language_settings::AllLanguageSettings,
};
use lsp::LanguageServerName;
use settings::{Settings, SettingsLocation};
use worktree::WorktreeId;
use settings::{WorktreeId,Settings, SettingsLocation};
use std::sync::OnceLock;
use util::rel_path::RelPath;

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: WorktreeId(value.project_worktree(cx).worktree_id as usize),
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,
)
@@ -5507,7 +5508,7 @@ impl ProjectItem for Buffer {
fn project_path(&self, cx: &App) -> Option<ProjectPath> {
self.file().map(|file| ProjectPath {
worktree_id: file.project_worktree(cx).worktree_id(),
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 {

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};
@@ -682,8 +682,9 @@ 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(&WorktreeId(location.worktree.worktree_id as usize))
if let Some(worktree_tasks) = parsed_templates
.worktree
.get_mut(&WorktreeId(location.worktree.worktree_id as usize))
{
worktree_tasks.remove(location.path);
}
@@ -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;
@@ -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(),
},
@@ -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

@@ -19,10 +19,9 @@ use rpc::{
resolve_toolchain_response::Response as ResolveResponsePayload,
},
};
use settings::ProjectWorktree;
use settings::{ProjectWorktree, WorktreeId};
use task::Shell;
use util::{ResultExt as _, rel_path::RelPath};
use worktree::WorktreeId;
use crate::{
ProjectEnvironment, ProjectPath,
@@ -399,7 +398,7 @@ pub struct LocalToolchainStore {
languages: Arc<LanguageRegistry>,
worktree_store: Entity<WorktreeStore>,
project_environment: Entity<ProjectEnvironment>,
active_toolchains: BTreeMap<(ProjectWorktree, LanguageName), BTreeMap<Arc<RelPath>, Toolchain>>,
active_toolchains: BTreeMap<(WorktreeId, LanguageName), BTreeMap<Arc<RelPath>, Toolchain>>,
manifest_tree: Entity<ManifestTree>,
fs: Arc<dyn Fs>,
}
@@ -408,7 +407,7 @@ pub struct LocalToolchainStore {
impl language::LocalLanguageToolchainStore for LocalStore {
fn active_toolchain(
self: Arc<Self>,
worktree_id: ProjectWorktree,
worktree_id: WorktreeId,
path: &Arc<RelPath>,
language_name: LanguageName,
cx: &mut AsyncApp,
@@ -425,14 +424,14 @@ impl language::LocalLanguageToolchainStore for LocalStore {
impl language::LanguageToolchainStore for RemoteStore {
async fn active_toolchain(
self: Arc<Self>,
worktree_id: ProjectWorktree,
worktree_id: WorktreeId,
path: Arc<RelPath>,
language_name: LanguageName,
cx: &mut AsyncApp,
) -> 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
@@ -443,7 +442,7 @@ pub struct EmptyToolchainStore;
impl language::LocalLanguageToolchainStore for EmptyToolchainStore {
fn active_toolchain(
self: Arc<Self>,
_: ProjectWorktree,
_: WorktreeId,
_: &Arc<RelPath>,
_: LanguageName,
_: &mut AsyncApp,

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())) })
}
}
@@ -463,7 +468,6 @@ impl WorktreeStore {
pub fn create_worktree(
&mut self,
abs_path: impl AsRef<Path>,
project_id_for_settings: u64,
visible: bool,
cx: &mut Context<Self>,
) -> Task<Result<Entity<Worktree>>> {
@@ -479,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(), project_id_for_settings, abs_path, visible, cx)
self.create_remote_worktree(
upstream_client.clone(),
abs_path,
visible,
cx,
)
}
}
WorktreeStoreState::Local { fs } => {
self.create_local_worktree(fs.clone(), project_id_for_settings, abs_path.clone(), visible, cx)
}
WorktreeStoreState::Local { fs } => self.create_local_worktree(
fs.clone(),
abs_path.clone(),
visible,
cx,
),
};
self.loading_worktrees
@@ -528,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,
})
@@ -548,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,

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

@@ -20,7 +20,7 @@ pub mod private {
use gpui::{App, Global};
use rust_embed::RustEmbed;
use std::{borrow::Cow, str};
use std::{borrow::Cow, fmt, str};
use util::asset_str;
pub use base_keymap_setting::*;
@@ -46,10 +46,50 @@ 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(pub usize);
impl From<WorktreeId> for usize {
fn from(value: WorktreeId) -> Self {
value.0
}
}
impl WorktreeId {
pub fn from_usize(handle_id: usize) -> Self {
Self(handle_id)
}
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
}
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: u64,
pub worktree_id: WorktreeId,
}
impl ProjectWorktree {
@@ -57,11 +97,17 @@ impl ProjectWorktree {
pub fn from_u64(n: u64) -> Self {
Self {
project_id: 0,
worktree_id: n,
worktree_id: WorktreeId(n as usize),
}
}
}
impl fmt::Display for WorktreeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
#[derive(RustEmbed)]
#[folder = "../../assets"]
#[include = "settings/*"]

View File

@@ -32,7 +32,8 @@ pub type EditorconfigProperties = ec4rs::Properties;
use crate::{
ActiveSettingsProfileName, FontFamilyName, IconThemeName, LanguageSettingsContent,
LanguageToSettingsMap, ThemeName, VsCodeSettings, ProjectWorktree, fallible_options,
LanguageToSettingsMap, ProjectWorktree, ThemeName, VsCodeSettings,
fallible_options,
merge_from::MergeFrom,
settings_content::{
ExtensionsSettingsContent, ProjectSettingsContent, SettingsContent, UserSettingsContent,
@@ -150,7 +151,8 @@ pub struct SettingsStore {
merged_settings: Rc<SettingsContent>,
local_settings: BTreeMap<(ProjectWorktree, Arc<RelPath>), SettingsContent>,
raw_editorconfig_settings: BTreeMap<(ProjectWorktree, Arc<RelPath>), (String, Option<Editorconfig>)>,
raw_editorconfig_settings:
BTreeMap<(ProjectWorktree, Arc<RelPath>), (String, Option<Editorconfig>)>,
_setting_file_updates: Task<()>,
setting_file_updates_tx:
@@ -246,7 +248,12 @@ pub trait AnySettingValue: 'static + Send + Sync {
fn value_for_path(&self, path: Option<SettingsLocation>) -> &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: ProjectWorktree, 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.
@@ -980,13 +987,8 @@ impl SettingsStore {
root_id: ProjectWorktree,
) -> impl '_ + Iterator<Item = (Arc<RelPath>, &ProjectSettingsContent)> {
self.local_settings
.range(
(root_id, RelPath::empty().into())
..(
ProjectWorktree{ project_id: root_id.project_id, worktree_id: root_id.worktree_id + 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))
}
@@ -995,13 +997,8 @@ impl SettingsStore {
root_id: ProjectWorktree,
) -> impl '_ + Iterator<Item = (Arc<RelPath>, String, Option<Editorconfig>)> {
self.raw_editorconfig_settings
.range(
(root_id, RelPath::empty().into())
..(
ProjectWorktree{ project_id: root_id.project_id, worktree_id: root_id.worktree_id + 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())
})
@@ -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: 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: ProjectWorktree, 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,8 @@ mod tests {
use std::num::NonZeroU32;
use crate::{
ClosePosition, ItemSettingsContent, VsCodeSettingsSource, default_settings, settings_content::LanguageSettingsContent, test_settings
ClosePosition, ItemSettingsContent, VsCodeSettingsSource, WorktreeId, default_settings,
settings_content::LanguageSettingsContent, test_settings,
};
use super::*;
@@ -1449,7 +1456,10 @@ mod tests {
ClosePosition::Left
);
let worktree = ProjectWorktree { project_id: 1, worktree_id: 1 };
let worktree = ProjectWorktree {
project_id: 1,
worktree_id: WorktreeId(1),
};
store
.set_local_settings(
@@ -2132,7 +2142,6 @@ mod tests {
let mut store = SettingsStore::new(cx, &test_settings());
store.register_setting::<DefaultLanguageSettings>();
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());

View File

@@ -38,7 +38,7 @@ use rpc::{
AnyProtoClient,
proto::{self, split_worktree_update},
};
use settings::{ProjectWorktree, Settings, SettingsLocation, SettingsStore};
use settings::{ProjectWorktree, Settings, SettingsLocation, SettingsStore, WorktreeId};
use smallvec::{SmallVec, smallvec};
use smol::channel::{self, Sender};
use std::{
@@ -71,45 +71,6 @@ pub use worktree_settings::WorktreeSettings;
pub const FS_WATCH_LATENCY: Duration = Duration::from_millis(100);
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)]
pub struct WorktreeId(pub usize);
impl From<WorktreeId> for usize {
fn from(value: WorktreeId) -> Self {
value.0
}
}
impl WorktreeId {
pub fn from_usize(handle_id: usize) -> Self {
Self(handle_id)
}
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
}
}
impl From<ProjectWorktree> for WorktreeId {
fn from(value: ProjectWorktree) -> Self {
Self(value.worktree_id as usize)
}
}
impl fmt::Display for WorktreeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
/// A set of local or remote files that are being opened as part of a project.
/// Responsible for tracking related FS (for local)/collab (for remote) events and corresponding updates.
/// Stores git repositories data and the diagnostics for the file(s).
@@ -535,7 +496,7 @@ impl Worktree {
let worktree_id = snapshot.id();
let settings_location = Some(SettingsLocation {
worktree: settings::ProjectWorktree {
worktree_id: worktree_id.to_proto(),
worktree_id,
project_id: project_id_for_settings,
},
path: RelPath::empty(),
@@ -658,7 +619,7 @@ impl Worktree {
SettingsLocation {
worktree: ProjectWorktree {
project_id: self.project_id_for_settings,
worktree_id: self.id.to_proto(),
worktree_id: self.id,
},
path: RelPath::empty(),
}
@@ -2110,7 +2071,7 @@ impl Snapshot {
pub fn project_worktree(&self) -> ProjectWorktree {
ProjectWorktree {
worktree_id: self.id.0 as u64,
worktree_id: self.id,
project_id: self.project_id_for_settings,
}
}