project: Always allocate WorktreeIDs on the remote client (#47936)
Closes https://github.com/zed-industries/zed/issues/40342 Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
1 parent
7efedfa812
commit
b26bc404ea
13 files changed
+187
-48
No files matched your search
@@ -2575,7 +2575,7 @@ mod tests {
|
||||
let worktree_id = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1);
|
||||
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize)
|
||||
worktrees[0].read(cx).id()
|
||||
});
|
||||
|
||||
// Open a file in dir2 to create navigation history.
|
||||
|
||||
@@ -388,6 +388,7 @@ mod tests {
|
||||
|
||||
use fs::FakeFs;
|
||||
use gpui::TestAppContext;
|
||||
use project::WorktreeId;
|
||||
use rand::Rng as _;
|
||||
use serde_json::json;
|
||||
use settings::SettingsStore;
|
||||
@@ -736,6 +737,7 @@ mod tests {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -760,6 +762,7 @@ mod tests {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -819,6 +822,7 @@ mod tests {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1210,10 +1210,7 @@ async fn test_create_file_for_multiple_worktrees(cx: &mut TestAppContext) {
|
||||
let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
|
||||
let (_worktree_id1, worktree_id2) = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
(
|
||||
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize),
|
||||
WorktreeId::from_usize(worktrees[1].entity_id().as_u64() as usize),
|
||||
)
|
||||
(worktrees[0].read(cx).id(), worktrees[1].read(cx).id())
|
||||
});
|
||||
|
||||
let b_path = ProjectPath {
|
||||
@@ -1342,7 +1339,7 @@ async fn test_path_distance_ordering(cx: &mut TestAppContext) {
|
||||
let worktree_id = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1);
|
||||
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize)
|
||||
worktrees[0].read(cx).id()
|
||||
});
|
||||
|
||||
// When workspace has an active item, sort items which are closer to that item
|
||||
@@ -1430,7 +1427,7 @@ async fn test_query_history(cx: &mut gpui::TestAppContext) {
|
||||
let worktree_id = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1);
|
||||
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize)
|
||||
worktrees[0].read(cx).id()
|
||||
});
|
||||
|
||||
// Open and close panels, getting their history items afterwards.
|
||||
@@ -1650,7 +1647,7 @@ async fn test_external_files_history(cx: &mut gpui::TestAppContext) {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1,);
|
||||
|
||||
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize)
|
||||
worktrees[0].read(cx).id()
|
||||
});
|
||||
workspace
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
@@ -1674,14 +1671,12 @@ async fn test_external_files_history(cx: &mut gpui::TestAppContext) {
|
||||
"External file should get opened in a new worktree"
|
||||
);
|
||||
|
||||
WorktreeId::from_usize(
|
||||
worktrees
|
||||
.into_iter()
|
||||
.find(|worktree| worktree.entity_id().as_u64() as usize != worktree_id.to_usize())
|
||||
.expect("New worktree should have a different id")
|
||||
.entity_id()
|
||||
.as_u64() as usize,
|
||||
)
|
||||
worktrees
|
||||
.into_iter()
|
||||
.find(|worktree| worktree.read(cx).id() != worktree_id)
|
||||
.expect("New worktree should have a different id")
|
||||
.read(cx)
|
||||
.id()
|
||||
});
|
||||
cx.dispatch_action(workspace::CloseActiveItem {
|
||||
save_intent: None,
|
||||
@@ -1807,7 +1802,7 @@ async fn test_search_preserves_history_items(cx: &mut gpui::TestAppContext) {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1,);
|
||||
|
||||
WorktreeId::from_usize(worktrees[0].entity_id().as_u64() as usize)
|
||||
worktrees[0].read(cx).id()
|
||||
});
|
||||
|
||||
// generate some history to select from
|
||||
|
||||
@@ -40,6 +40,7 @@ use crate::{
|
||||
lsp_store::{SymbolLocation, log_store::LogKind},
|
||||
project_search::SearchResultsHandle,
|
||||
trusted_worktrees::{PathTrust, RemoteHostLocation, TrustedWorktrees},
|
||||
worktree_store::WorktreeIdCounter,
|
||||
};
|
||||
pub use agent_registry_store::{AgentRegistryStore, RegistryAgent};
|
||||
pub use agent_server_store::{
|
||||
@@ -1118,7 +1119,8 @@ impl Project {
|
||||
cx.spawn(async move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx).await)
|
||||
.detach();
|
||||
let snippets = SnippetProvider::new(fs.clone(), BTreeSet::from_iter([]), cx);
|
||||
let worktree_store = cx.new(|_| WorktreeStore::local(false, fs.clone()));
|
||||
let worktree_store =
|
||||
cx.new(|cx| WorktreeStore::local(false, fs.clone(), WorktreeIdCounter::get(cx)));
|
||||
if flags.init_worktree_trust {
|
||||
trusted_worktrees::track_worktree_trust(
|
||||
worktree_store.clone(),
|
||||
@@ -1325,12 +1327,13 @@ impl Project {
|
||||
remote.connection_options(),
|
||||
)
|
||||
});
|
||||
let worktree_store = cx.new(|_| {
|
||||
let worktree_store = cx.new(|cx| {
|
||||
WorktreeStore::remote(
|
||||
false,
|
||||
remote_proto.clone(),
|
||||
REMOTE_SERVER_PROJECT_ID,
|
||||
path_style,
|
||||
WorktreeIdCounter::get(cx),
|
||||
)
|
||||
});
|
||||
|
||||
@@ -1553,6 +1556,7 @@ impl Project {
|
||||
|
||||
remote_proto.add_entity_message_handler(Self::handle_find_search_candidates_cancel);
|
||||
BufferStore::init(&remote_proto);
|
||||
WorktreeStore::init_remote(&remote_proto);
|
||||
LspStore::init(&remote_proto);
|
||||
SettingsObserver::init(&remote_proto);
|
||||
TaskStore::init(Some(&remote_proto));
|
||||
@@ -1632,12 +1636,13 @@ impl Project {
|
||||
PathStyle::Posix
|
||||
};
|
||||
|
||||
let worktree_store = cx.new(|_| {
|
||||
let worktree_store = cx.new(|cx| {
|
||||
WorktreeStore::remote(
|
||||
true,
|
||||
client.clone().into(),
|
||||
response.payload.project_id,
|
||||
path_style,
|
||||
WorktreeIdCounter::get(cx),
|
||||
)
|
||||
});
|
||||
let buffer_store = cx.new(|cx| {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, atomic::AtomicUsize},
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicU64, AtomicUsize},
|
||||
},
|
||||
};
|
||||
|
||||
use anyhow::{Context as _, Result, anyhow, bail};
|
||||
@@ -8,8 +11,10 @@ use collections::HashMap;
|
||||
use fs::{Fs, copy_recursive};
|
||||
use futures::{FutureExt, future::Shared};
|
||||
use gpui::{
|
||||
App, AppContext as _, AsyncApp, Context, Entity, EntityId, EventEmitter, Task, WeakEntity,
|
||||
App, AppContext as _, AsyncApp, Context, Entity, EntityId, EventEmitter, Global, Task,
|
||||
WeakEntity,
|
||||
};
|
||||
use itertools::Either;
|
||||
use rpc::{
|
||||
AnyProtoClient, ErrorExt, TypedEnvelope,
|
||||
proto::{self, REMOTE_SERVER_PROJECT_ID},
|
||||
@@ -38,8 +43,30 @@ enum WorktreeStoreState {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WorktreeIdCounter(Arc<AtomicU64>);
|
||||
|
||||
impl Default for WorktreeIdCounter {
|
||||
fn default() -> Self {
|
||||
Self(Arc::new(AtomicU64::new(1)))
|
||||
}
|
||||
}
|
||||
|
||||
impl WorktreeIdCounter {
|
||||
pub fn get(cx: &mut App) -> Self {
|
||||
cx.default_global::<Self>().clone()
|
||||
}
|
||||
|
||||
fn next(&self) -> u64 {
|
||||
self.0.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Global for WorktreeIdCounter {}
|
||||
|
||||
pub struct WorktreeStore {
|
||||
next_entry_id: Arc<AtomicUsize>,
|
||||
next_worktree_id: WorktreeIdCounter,
|
||||
downstream_client: Option<(AnyProtoClient, u64)>,
|
||||
retain_worktrees: bool,
|
||||
worktrees: Vec<WorktreeHandle>,
|
||||
@@ -74,9 +101,18 @@ 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 init_remote(client: &AnyProtoClient) {
|
||||
client.add_entity_request_handler(Self::handle_allocate_worktree_id);
|
||||
}
|
||||
|
||||
pub fn local(
|
||||
retain_worktrees: bool,
|
||||
fs: Arc<dyn Fs>,
|
||||
next_worktree_id: WorktreeIdCounter,
|
||||
) -> Self {
|
||||
Self {
|
||||
next_entry_id: Default::default(),
|
||||
next_worktree_id,
|
||||
loading_worktrees: Default::default(),
|
||||
downstream_client: None,
|
||||
worktrees: Vec::new(),
|
||||
@@ -92,9 +128,11 @@ impl WorktreeStore {
|
||||
upstream_client: AnyProtoClient,
|
||||
upstream_project_id: u64,
|
||||
path_style: PathStyle,
|
||||
next_worktree_id: WorktreeIdCounter,
|
||||
) -> Self {
|
||||
Self {
|
||||
next_entry_id: Default::default(),
|
||||
next_worktree_id,
|
||||
loading_worktrees: Default::default(),
|
||||
downstream_client: None,
|
||||
worktrees: Vec::new(),
|
||||
@@ -109,6 +147,31 @@ impl WorktreeStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_worktree_id(&self) -> impl Future<Output = Result<WorktreeId>> + use<> {
|
||||
let strategy = match (&self.state, &self.downstream_client) {
|
||||
// we are a remote server, the client is in charge of assigning worktree ids
|
||||
(WorktreeStoreState::Local { .. }, Some((client, REMOTE_SERVER_PROJECT_ID))) => {
|
||||
Either::Left(client.clone())
|
||||
}
|
||||
// we are just a local zed project, we can assign ids
|
||||
(WorktreeStoreState::Local { .. }, _) => Either::Right(self.next_worktree_id.next()),
|
||||
// we are connected to a remote server, we are in charge of assigning worktree ids
|
||||
(WorktreeStoreState::Remote { .. }, _) => Either::Right(self.next_worktree_id.next()),
|
||||
};
|
||||
async move {
|
||||
match strategy {
|
||||
Either::Left(client) => Ok(client
|
||||
.request(proto::AllocateWorktreeId {
|
||||
project_id: REMOTE_SERVER_PROJECT_ID,
|
||||
})
|
||||
.await?
|
||||
.worktree_id),
|
||||
Either::Right(id) => Ok(id),
|
||||
}
|
||||
.map(WorktreeId::from_proto)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disable_scanner(&mut self) {
|
||||
self.scanning_enabled = false;
|
||||
}
|
||||
@@ -600,13 +663,17 @@ impl WorktreeStore {
|
||||
let next_entry_id = self.next_entry_id.clone();
|
||||
let scanning_enabled = self.scanning_enabled;
|
||||
|
||||
let next_worktree_id = self.next_worktree_id();
|
||||
|
||||
cx.spawn(async move |this, cx| {
|
||||
let worktree_id = next_worktree_id.await?;
|
||||
let worktree = Worktree::local(
|
||||
SanitizedPath::cast_arc(abs_path.clone()),
|
||||
visible,
|
||||
fs,
|
||||
next_entry_id,
|
||||
scanning_enabled,
|
||||
worktree_id,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
@@ -1078,6 +1145,15 @@ impl WorktreeStore {
|
||||
Worktree::handle_expand_all_for_entry(worktree, envelope.payload, cx).await
|
||||
}
|
||||
|
||||
pub async fn handle_allocate_worktree_id(
|
||||
_this: Entity<Self>,
|
||||
_envelope: TypedEnvelope<proto::AllocateWorktreeId>,
|
||||
cx: AsyncApp,
|
||||
) -> Result<proto::AllocateWorktreeIdResponse> {
|
||||
let worktree_id = cx.update(|cx| WorktreeIdCounter::get(cx).next());
|
||||
Ok(proto::AllocateWorktreeIdResponse { worktree_id })
|
||||
}
|
||||
|
||||
pub fn fs(&self) -> Option<Arc<dyn Fs>> {
|
||||
match &self.state {
|
||||
WorktreeStoreState::Local { fs } => Some(fs.clone()),
|
||||
|
||||
@@ -2,8 +2,8 @@ use anyhow::Result;
|
||||
use collections::HashMap;
|
||||
use gpui::{AppContext, AsyncApp, SharedString, Task, TestAppContext};
|
||||
use node_runtime::NodeRuntime;
|
||||
use project::agent_server_store::*;
|
||||
use project::worktree_store::WorktreeStore;
|
||||
use project::{agent_server_store::*, worktree_store::WorktreeIdCounter};
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
|
||||
#[test]
|
||||
@@ -131,7 +131,8 @@ fn archive_launcher_constructs_with_all_fields() {
|
||||
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(|cx| WorktreeStore::local(false, fs.clone(), WorktreeIdCounter::get(cx)));
|
||||
let project_environment = cx.new(|cx| {
|
||||
crate::ProjectEnvironment::new(None, worktree_store.downgrade(), None, false, cx)
|
||||
});
|
||||
@@ -212,7 +213,8 @@ async fn test_node_command_uses_managed_runtime(cx: &mut TestAppContext) {
|
||||
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(|cx| WorktreeStore::local(false, fs.clone(), WorktreeIdCounter::get(cx)));
|
||||
let project_environment = cx.new(|cx| {
|
||||
crate::ProjectEnvironment::new(None, worktree_store.downgrade(), None, false, cx)
|
||||
});
|
||||
@@ -255,7 +257,8 @@ async fn test_commands_run_in_extraction_directory(cx: &mut TestAppContext) {
|
||||
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(|cx| WorktreeStore::local(false, fs.clone(), WorktreeIdCounter::get(cx)));
|
||||
let project_environment = cx.new(|cx| {
|
||||
crate::ProjectEnvironment::new(None, worktree_store.downgrade(), None, false, cx)
|
||||
});
|
||||
|
||||
@@ -162,22 +162,33 @@ message UpdateUserSettings {
|
||||
}
|
||||
|
||||
message TrustWorktrees {
|
||||
uint64 project_id = 1;
|
||||
repeated PathTrust trusted_paths = 2;
|
||||
uint64 project_id = 1;
|
||||
repeated PathTrust trusted_paths = 2;
|
||||
}
|
||||
|
||||
message PathTrust {
|
||||
oneof content {
|
||||
uint64 worktree_id = 2;
|
||||
string abs_path = 3;
|
||||
}
|
||||
oneof content {
|
||||
uint64 worktree_id = 2;
|
||||
string abs_path = 3;
|
||||
}
|
||||
|
||||
reserved 1;
|
||||
reserved 1;
|
||||
}
|
||||
|
||||
message RestrictWorktrees {
|
||||
uint64 project_id = 1;
|
||||
repeated uint64 worktree_ids = 3;
|
||||
uint64 project_id = 1;
|
||||
repeated uint64 worktree_ids = 3;
|
||||
|
||||
reserved 2;
|
||||
reserved 2;
|
||||
}
|
||||
|
||||
// Request from the remote server to the client to allocate a new worktree ID.
|
||||
// This allows the client to maintain a single WorktreeIdCounter that prevents
|
||||
// ID collisions when connected to multiple remote servers.
|
||||
message AllocateWorktreeId {
|
||||
uint64 project_id = 1;
|
||||
}
|
||||
|
||||
message AllocateWorktreeIdResponse {
|
||||
uint64 worktree_id = 1;
|
||||
}
|
||||
@@ -455,7 +455,10 @@ message Envelope {
|
||||
FindSearchCandidatesChunk find_search_candidates_chunk = 409;
|
||||
FindSearchCandidatesCancelled find_search_candidates_cancelled = 410;
|
||||
GetContextServerCommand get_context_server_command = 411;
|
||||
ContextServerCommand context_server_command = 412; // current max
|
||||
ContextServerCommand context_server_command = 412;
|
||||
|
||||
AllocateWorktreeId allocate_worktree_id = 413;
|
||||
AllocateWorktreeIdResponse allocate_worktree_id_response = 414; // current max
|
||||
}
|
||||
|
||||
reserved 87 to 88;
|
||||
|
||||
@@ -33,6 +33,8 @@ messages!(
|
||||
(AddWorktree, Foreground),
|
||||
(AddWorktreeResponse, Foreground),
|
||||
(AdvertiseContexts, Foreground),
|
||||
(AllocateWorktreeId, Foreground),
|
||||
(AllocateWorktreeIdResponse, Foreground),
|
||||
(ApplyCodeAction, Background),
|
||||
(ApplyCodeActionResponse, Background),
|
||||
(ApplyCompletionAdditionalEdits, Background),
|
||||
@@ -352,6 +354,7 @@ messages!(
|
||||
);
|
||||
|
||||
request_messages!(
|
||||
(AllocateWorktreeId, AllocateWorktreeIdResponse),
|
||||
(ApplyCodeAction, ApplyCodeActionResponse),
|
||||
(
|
||||
ApplyCompletionAdditionalEdits,
|
||||
@@ -561,6 +564,7 @@ entity_messages!(
|
||||
{project_id, ShareProject},
|
||||
AddProjectCollaborator,
|
||||
AddWorktree,
|
||||
AllocateWorktreeId,
|
||||
ApplyCodeAction,
|
||||
ApplyCompletionAdditionalEdits,
|
||||
BlameBuffer,
|
||||
|
||||
@@ -25,7 +25,7 @@ use project::{
|
||||
search::SearchQuery,
|
||||
task_store::TaskStore,
|
||||
trusted_worktrees::{PathTrust, RemoteHostLocation, TrustedWorktrees},
|
||||
worktree_store::WorktreeStore,
|
||||
worktree_store::{WorktreeIdCounter, WorktreeStore},
|
||||
};
|
||||
use rpc::{
|
||||
AnyProtoClient, TypedEnvelope,
|
||||
@@ -98,7 +98,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(true, fs.clone(), WorktreeIdCounter::get(cx));
|
||||
store.shared(REMOTE_SERVER_PROJECT_ID, session.clone(), cx);
|
||||
store
|
||||
});
|
||||
@@ -482,7 +482,12 @@ impl HeadlessProject {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let next_worktree_id = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.worktree_store
|
||||
.update(cx, |worktree_store, _| worktree_store.next_worktree_id())
|
||||
})
|
||||
.await?;
|
||||
let worktree = this
|
||||
.read_with(&cx.clone(), |this, _| {
|
||||
Worktree::local(
|
||||
@@ -491,6 +496,7 @@ impl HeadlessProject {
|
||||
this.fs.clone(),
|
||||
this.next_entry_id.clone(),
|
||||
true,
|
||||
next_worktree_id,
|
||||
&mut cx,
|
||||
)
|
||||
})
|
||||
@@ -754,7 +760,7 @@ impl HeadlessProject {
|
||||
buffer_store.open_buffer(
|
||||
ProjectPath {
|
||||
worktree_id: worktree.read(cx).id(),
|
||||
path: path,
|
||||
path,
|
||||
},
|
||||
cx,
|
||||
)
|
||||
|
||||
@@ -368,6 +368,7 @@ impl Worktree {
|
||||
fs: Arc<dyn Fs>,
|
||||
next_entry_id: Arc<AtomicUsize>,
|
||||
scanning_enabled: bool,
|
||||
worktree_id: WorktreeId,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Self>> {
|
||||
let abs_path = path.into();
|
||||
@@ -404,7 +405,7 @@ impl Worktree {
|
||||
repo_exclude_by_work_dir_abs_path: Default::default(),
|
||||
git_repositories: Default::default(),
|
||||
snapshot: Snapshot::new(
|
||||
cx.entity_id().as_u64(),
|
||||
worktree_id,
|
||||
abs_path
|
||||
.file_name()
|
||||
.and_then(|f| f.to_str())
|
||||
@@ -493,7 +494,7 @@ impl Worktree {
|
||||
) -> Entity<Self> {
|
||||
cx.new(|cx: &mut Context<Self>| {
|
||||
let snapshot = Snapshot::new(
|
||||
worktree.id,
|
||||
WorktreeId::from_proto(worktree.id),
|
||||
RelPath::from_proto(&worktree.root_name)
|
||||
.unwrap_or_else(|_| RelPath::empty().into()),
|
||||
Path::new(&worktree.abs_path).into(),
|
||||
@@ -1831,7 +1832,7 @@ impl LocalWorktree {
|
||||
.unbounded_send((self.snapshot(), Arc::default()))
|
||||
.ok();
|
||||
|
||||
let worktree_id = cx.entity_id().as_u64();
|
||||
let worktree_id = self.id.to_proto();
|
||||
let _maintain_remote_snapshot = cx.background_spawn(async move {
|
||||
let mut is_first = true;
|
||||
while let Some((snapshot, entry_changes)) = snapshots_rx.next().await {
|
||||
@@ -2137,13 +2138,13 @@ impl RemoteWorktree {
|
||||
|
||||
impl Snapshot {
|
||||
pub fn new(
|
||||
id: u64,
|
||||
id: WorktreeId,
|
||||
root_name: Arc<RelPath>,
|
||||
abs_path: Arc<Path>,
|
||||
path_style: PathStyle,
|
||||
) -> Self {
|
||||
Snapshot {
|
||||
id: WorktreeId::from_usize(id as usize),
|
||||
id,
|
||||
abs_path: SanitizedPath::from_arc(abs_path),
|
||||
path_style,
|
||||
root_char_bag: root_name
|
||||
|
||||
@@ -12,7 +12,7 @@ use rand::prelude::*;
|
||||
use worktree::{Entry, EntryKind, Event, PathChange, Worktree, WorktreeModelHandle};
|
||||
|
||||
use serde_json::json;
|
||||
use settings::SettingsStore;
|
||||
use settings::{SettingsStore, WorktreeId};
|
||||
use std::{
|
||||
env,
|
||||
fmt::Write,
|
||||
@@ -49,6 +49,7 @@ async fn test_traversal(cx: &mut TestAppContext) {
|
||||
fs,
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -114,6 +115,7 @@ async fn test_circular_symlinks(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -214,6 +216,7 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -365,6 +368,7 @@ async fn test_renaming_case_only(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -443,6 +447,7 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -608,6 +613,7 @@ async fn test_dirs_no_longer_ignored(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -709,6 +715,7 @@ async fn test_write_file(cx: &mut TestAppContext) {
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -807,6 +814,7 @@ async fn test_file_scan_inclusions(cx: &mut TestAppContext) {
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -873,6 +881,7 @@ async fn test_file_scan_exclusions_overrules_inclusions(cx: &mut TestAppContext)
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -932,6 +941,7 @@ async fn test_file_scan_inclusions_reindexes_on_setting_change(cx: &mut TestAppC
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1018,6 +1028,7 @@ async fn test_file_scan_exclusions(cx: &mut TestAppContext) {
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1100,6 +1111,7 @@ async fn test_hidden_files(cx: &mut TestAppContext) {
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1211,6 +1223,7 @@ async fn test_fs_events_in_exclusions(cx: &mut TestAppContext) {
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1323,6 +1336,7 @@ async fn test_fs_events_in_dot_git_worktree(cx: &mut TestAppContext) {
|
||||
Arc::new(RealFs::new(None, cx.executor())),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1362,6 +1376,7 @@ async fn test_create_directory_during_initial_scan(cx: &mut TestAppContext) {
|
||||
fs,
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1431,6 +1446,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
|
||||
fs_fake,
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1473,6 +1489,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
|
||||
fs_real,
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1582,6 +1599,7 @@ async fn test_create_file_in_expanded_gitignored_dir(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1678,6 +1696,7 @@ async fn test_fs_event_for_gitignored_dir_does_not_lose_contents(cx: &mut TestAp
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1756,6 +1775,7 @@ async fn test_random_worktree_operations_during_initial_scan(
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1847,6 +1867,7 @@ async fn test_random_worktree_changes(cx: &mut TestAppContext, mut rng: StdRng)
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -1920,6 +1941,7 @@ async fn test_random_worktree_changes(cx: &mut TestAppContext, mut rng: StdRng)
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2244,6 +2266,7 @@ async fn test_private_single_file_worktree(cx: &mut TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2277,6 +2300,7 @@ async fn test_repository_above_root(executor: BackgroundExecutor, cx: &mut TestA
|
||||
fs.clone(),
|
||||
Arc::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2343,6 +2367,7 @@ async fn test_global_gitignore(executor: BackgroundExecutor, cx: &mut TestAppCon
|
||||
fs.clone(),
|
||||
Arc::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2449,6 +2474,7 @@ async fn test_repo_exclude(executor: BackgroundExecutor, cx: &mut TestAppContext
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2665,6 +2691,7 @@ async fn test_load_file_encoding(cx: &mut TestAppContext) {
|
||||
fs,
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2728,6 +2755,7 @@ async fn test_write_file_encoding(cx: &mut gpui::TestAppContext) {
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
@@ -2866,6 +2894,7 @@ async fn test_refresh_entries_for_paths_creates_ancestors(cx: &mut TestAppContex
|
||||
fs.clone(),
|
||||
Default::default(),
|
||||
false, // Disable scanning so the initial scan doesn't discover any entries
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::{
|
||||
|
||||
use fs::RealFs;
|
||||
use gpui::Application;
|
||||
use settings::WorktreeId;
|
||||
use worktree::Worktree;
|
||||
|
||||
fn main() {
|
||||
@@ -27,6 +28,7 @@ fn main() {
|
||||
fs,
|
||||
Arc::new(AtomicUsize::new(0)),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
cx,
|
||||
)
|
||||
.await
|
||||
|
||||
Reference in new issue
Block a user