From 43da36948bdb0a230823f173d9a3e339e0ce2811 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 6 Oct 2023 13:14:39 -0700 Subject: [PATCH 1/4] Add a crate-dep-graph script for showing the crate dependency graph --- script/crate-dep-graph | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 script/crate-dep-graph diff --git a/script/crate-dep-graph b/script/crate-dep-graph new file mode 100755 index 0000000000000000000000000000000000000000..25285cc097c01331e36ea34a9b5a9ef622f43342 --- /dev/null +++ b/script/crate-dep-graph @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +if [[ -x cargo-depgraph ]]; then + cargo install cargo-depgraph +fi + +graph_file=target/crate-graph.html + +cargo depgraph \ + --workspace-only \ + --offline \ + --root=zed,cli,collab \ + --dedup-transitive-deps \ + | dot -Tsvg > $graph_file + +echo "open $graph_file" +open $graph_file From 17925ed5631f86a8564c885172cd9521012b2edc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 6 Oct 2023 13:14:53 -0700 Subject: [PATCH 2/4] Remove unnecessary dependencies on client and rpc --- Cargo.lock | 1 - crates/fs/Cargo.toml | 1 - crates/fs/src/repository.rs | 20 +------------------- crates/language/Cargo.toml | 1 - crates/project/src/worktree.rs | 22 ++++++++++++++++++++-- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c57548057d9d3618d194ee02f9ae57bf63958394..1b6583f067e7edf81255dc7b892d10afaaf8b937 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2832,7 +2832,6 @@ dependencies = [ "parking_lot 0.11.2", "regex", "rope", - "rpc", "serde", "serde_derive", "serde_json", diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index 441ce6f9c7b678101d676d7e8f31a90143c42d3b..11a34bcecb2674a652322409a072752cdc167ee6 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -13,7 +13,6 @@ rope = { path = "../rope" } text = { path = "../text" } util = { path = "../util" } sum_tree = { path = "../sum_tree" } -rpc = { path = "../rpc" } anyhow.workspace = true async-trait.workspace = true diff --git a/crates/fs/src/repository.rs b/crates/fs/src/repository.rs index 2b2aebe67959ed977c96ed60b36cf4c7ce3d23d2..4637a7f75408c74a4d398b8eb60f21d6ba76ab33 100644 --- a/crates/fs/src/repository.rs +++ b/crates/fs/src/repository.rs @@ -2,7 +2,6 @@ use anyhow::Result; use collections::HashMap; use git2::{BranchType, StatusShow}; use parking_lot::Mutex; -use rpc::proto; use serde_derive::{Deserialize, Serialize}; use std::{ cmp::Ordering, @@ -23,6 +22,7 @@ pub struct Branch { /// Timestamp of most recent commit, normalized to Unix Epoch format. pub unix_timestamp: Option, } + #[async_trait::async_trait] pub trait GitRepository: Send { fn reload_index(&self); @@ -358,24 +358,6 @@ impl GitFileStatus { } } } - - pub fn from_proto(git_status: Option) -> Option { - git_status.and_then(|status| { - proto::GitStatus::from_i32(status).map(|status| match status { - proto::GitStatus::Added => GitFileStatus::Added, - proto::GitStatus::Modified => GitFileStatus::Modified, - proto::GitStatus::Conflict => GitFileStatus::Conflict, - }) - }) - } - - pub fn to_proto(self) -> i32 { - match self { - GitFileStatus::Added => proto::GitStatus::Added as i32, - GitFileStatus::Modified => proto::GitStatus::Modified as i32, - GitFileStatus::Conflict => proto::GitStatus::Conflict as i32, - } - } } #[derive(Clone, Debug, Ord, Hash, PartialOrd, Eq, PartialEq)] diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index 4771fc70833660ccb018d9ffd45362f018901e4a..cf468020ceef0bc2c97b976beb018117a03585ac 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -22,7 +22,6 @@ test-support = [ ] [dependencies] -client = { path = "../client" } clock = { path = "../clock" } collections = { path = "../collections" } fuzzy = { path = "../fuzzy" } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 2de36710333c70aa0c0554a2b829181a5cb52da7..a38e43cd87bd16ad257686d5fc0a06336fb6895d 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -4310,7 +4310,7 @@ impl<'a> From<&'a Entry> for proto::Entry { is_symlink: entry.is_symlink, is_ignored: entry.is_ignored, is_external: entry.is_external, - git_status: entry.git_status.map(|status| status.to_proto()), + git_status: entry.git_status.map(git_status_to_proto), } } } @@ -4337,7 +4337,7 @@ impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry { is_symlink: entry.is_symlink, is_ignored: entry.is_ignored, is_external: entry.is_external, - git_status: GitFileStatus::from_proto(entry.git_status), + git_status: git_status_from_proto(entry.git_status), }) } else { Err(anyhow!( @@ -4366,3 +4366,21 @@ fn combine_git_statuses( unstaged } } + +fn git_status_from_proto(git_status: Option) -> Option { + git_status.and_then(|status| { + proto::GitStatus::from_i32(status).map(|status| match status { + proto::GitStatus::Added => GitFileStatus::Added, + proto::GitStatus::Modified => GitFileStatus::Modified, + proto::GitStatus::Conflict => GitFileStatus::Conflict, + }) + }) +} + +fn git_status_to_proto(status: GitFileStatus) -> i32 { + match status { + GitFileStatus::Added => proto::GitStatus::Added as i32, + GitFileStatus::Modified => proto::GitStatus::Modified as i32, + GitFileStatus::Conflict => proto::GitStatus::Conflict as i32, + } +} From 3412bb75bebcc8ec4f77234baa9acca7fb1bc48f Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 6 Oct 2023 13:39:10 -0700 Subject: [PATCH 3/4] Remove call -> channel dependency --- Cargo.lock | 1 - crates/call/Cargo.toml | 1 - crates/call/src/call.rs | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b6583f067e7edf81255dc7b892d10afaaf8b937..60d7b0b7d5980b23ab87c4a716eca2825bdb5f54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1082,7 +1082,6 @@ dependencies = [ "anyhow", "async-broadcast", "audio", - "channel", "client", "collections", "fs", diff --git a/crates/call/Cargo.toml b/crates/call/Cargo.toml index b4e94fe56c3b12533d232eacf30c5edd633d5a03..eb448d8d8d089369c724f49e5911a8946598f8a4 100644 --- a/crates/call/Cargo.toml +++ b/crates/call/Cargo.toml @@ -20,7 +20,6 @@ test-support = [ [dependencies] audio = { path = "../audio" } -channel = { path = "../channel" } client = { path = "../client" } collections = { path = "../collections" } gpui = { path = "../gpui" } diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index d86ed1be37e38da86bb9715e187528447e5b1abc..08463413257b4b10972ad08ab7c64d181599d914 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -5,7 +5,6 @@ pub mod room; use anyhow::{anyhow, Result}; use audio::Audio; use call_settings::CallSettings; -use channel::ChannelId; use client::{ proto, ClickhouseEvent, Client, TelemetrySettings, TypedEnvelope, User, UserStore, ZED_ALWAYS_ACTIVE, @@ -79,7 +78,7 @@ impl ActiveCall { } } - pub fn channel_id(&self, cx: &AppContext) -> Option { + pub fn channel_id(&self, cx: &AppContext) -> Option { self.room()?.read(cx).channel_id() } From f8ca86c6a7d32f45293c6837fa23bf5bf4a6b060 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 6 Oct 2023 14:16:08 -0700 Subject: [PATCH 4/4] Remove workspace -> channel dependency --- Cargo.lock | 1 - crates/channel/src/channel.rs | 10 +++--- crates/channel/src/channel_store.rs | 11 ++++++- crates/channel/src/channel_store_tests.rs | 4 +-- crates/collab/src/tests/test_server.rs | 39 ++++++++++------------- crates/collab_ui/src/channel_view.rs | 2 +- crates/collab_ui/src/chat_panel.rs | 2 +- crates/collab_ui/src/collab_panel.rs | 2 +- crates/workspace/Cargo.toml | 1 - crates/workspace/src/workspace.rs | 9 +----- crates/zed/src/main.rs | 6 +--- crates/zed/src/zed.rs | 1 + 12 files changed, 41 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60d7b0b7d5980b23ab87c4a716eca2825bdb5f54..24d835942148753ff05faac377bebd5b57d00515 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9969,7 +9969,6 @@ dependencies = [ "async-recursion 1.0.5", "bincode", "call", - "channel", "client", "collections", "context_menu", diff --git a/crates/channel/src/channel.rs b/crates/channel/src/channel.rs index 160b8441ffd74f1ca835c70234fcbb166c7fa477..d31d4b3c8c9e77e94661835c06ea234c70ded416 100644 --- a/crates/channel/src/channel.rs +++ b/crates/channel/src/channel.rs @@ -2,19 +2,21 @@ mod channel_buffer; mod channel_chat; mod channel_store; +use client::{Client, UserStore}; +use gpui::{AppContext, ModelHandle}; +use std::sync::Arc; + pub use channel_buffer::{ChannelBuffer, ChannelBufferEvent, ACKNOWLEDGE_DEBOUNCE_INTERVAL}; pub use channel_chat::{ChannelChat, ChannelChatEvent, ChannelMessage, ChannelMessageId}; pub use channel_store::{ Channel, ChannelData, ChannelEvent, ChannelId, ChannelMembership, ChannelPath, ChannelStore, }; -use client::Client; -use std::sync::Arc; - #[cfg(test)] mod channel_store_tests; -pub fn init(client: &Arc) { +pub fn init(client: &Arc, user_store: ModelHandle, cx: &mut AppContext) { + channel_store::init(client, user_store, cx); channel_buffer::init(client); channel_chat::init(client); } diff --git a/crates/channel/src/channel_store.rs b/crates/channel/src/channel_store.rs index bd72c92c7db768c558f7bc1b39a371f01f5dfd6c..8cdd11b4ec224c18bc0b0d29a58510cb4e826954 100644 --- a/crates/channel/src/channel_store.rs +++ b/crates/channel/src/channel_store.rs @@ -2,6 +2,7 @@ mod channel_index; use crate::{channel_buffer::ChannelBuffer, channel_chat::ChannelChat}; use anyhow::{anyhow, Result}; +use channel_index::ChannelIndex; use client::{Client, Subscription, User, UserId, UserStore}; use collections::{hash_map, HashMap, HashSet}; use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt}; @@ -14,7 +15,11 @@ use serde_derive::{Deserialize, Serialize}; use std::{borrow::Cow, hash::Hash, mem, ops::Deref, sync::Arc, time::Duration}; use util::ResultExt; -use self::channel_index::ChannelIndex; +pub fn init(client: &Arc, user_store: ModelHandle, cx: &mut AppContext) { + let channel_store = + cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); + cx.set_global(channel_store); +} pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30); @@ -71,6 +76,10 @@ enum OpenedModelHandle { } impl ChannelStore { + pub fn global(cx: &AppContext) -> ModelHandle { + cx.global::>().clone() + } + pub fn new( client: Arc, user_store: ModelHandle, diff --git a/crates/channel/src/channel_store_tests.rs b/crates/channel/src/channel_store_tests.rs index 41acafa3a30525b4c1fd54ecf479a674b2f67df0..9303a52092e13a1592e4a5786c4ed636b969cb73 100644 --- a/crates/channel/src/channel_store_tests.rs +++ b/crates/channel/src/channel_store_tests.rs @@ -340,10 +340,10 @@ fn init_test(cx: &mut AppContext) -> ModelHandle { cx.foreground().forbid_parking(); cx.set_global(SettingsStore::test(cx)); - crate::init(&client); client::init(&client, cx); + crate::init(&client, user_store, cx); - cx.add_model(|cx| ChannelStore::new(client, user_store, cx)) + ChannelStore::global(cx) } fn update_channels( diff --git a/crates/collab/src/tests/test_server.rs b/crates/collab/src/tests/test_server.rs index e10ded7d953f3872a3056a29940a7610db73de41..2e13874125472cd53b68d4d688c90ca02569615a 100644 --- a/crates/collab/src/tests/test_server.rs +++ b/crates/collab/src/tests/test_server.rs @@ -44,6 +44,7 @@ pub struct TestServer { pub struct TestClient { pub username: String, pub app_state: Arc, + channel_store: ModelHandle, state: RefCell, } @@ -206,15 +207,12 @@ impl TestServer { let fs = FakeFs::new(cx.background()); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx)); let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx)); - let channel_store = - cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); let mut language_registry = LanguageRegistry::test(); language_registry.set_executor(cx.background()); let app_state = Arc::new(workspace::AppState { client: client.clone(), user_store: user_store.clone(), workspace_store, - channel_store: channel_store.clone(), languages: Arc::new(language_registry), fs: fs.clone(), build_window_options: |_, _, _| Default::default(), @@ -231,7 +229,7 @@ impl TestServer { workspace::init(app_state.clone(), cx); audio::init((), cx); call::init(client.clone(), user_store.clone(), cx); - channel::init(&client); + channel::init(&client, user_store, cx); }); client @@ -242,6 +240,7 @@ impl TestServer { let client = TestClient { app_state, username: name.to_string(), + channel_store: cx.read(ChannelStore::global).clone(), state: Default::default(), }; client.wait_for_current_user(cx).await; @@ -310,10 +309,9 @@ impl TestServer { admin: (&TestClient, &mut TestAppContext), members: &mut [(&TestClient, &mut TestAppContext)], ) -> u64 { - let (admin_client, admin_cx) = admin; - let channel_id = admin_client - .app_state - .channel_store + let (_, admin_cx) = admin; + let channel_id = admin_cx + .read(ChannelStore::global) .update(admin_cx, |channel_store, cx| { channel_store.create_channel(channel, parent, cx) }) @@ -321,9 +319,8 @@ impl TestServer { .unwrap(); for (member_client, member_cx) in members { - admin_client - .app_state - .channel_store + admin_cx + .read(ChannelStore::global) .update(admin_cx, |channel_store, cx| { channel_store.invite_member( channel_id, @@ -337,9 +334,8 @@ impl TestServer { admin_cx.foreground().run_until_parked(); - member_client - .app_state - .channel_store + member_cx + .read(ChannelStore::global) .update(*member_cx, |channels, _| { channels.respond_to_channel_invite(channel_id, true) }) @@ -447,7 +443,7 @@ impl TestClient { } pub fn channel_store(&self) -> &ModelHandle { - &self.app_state.channel_store + &self.channel_store } pub fn user_store(&self) -> &ModelHandle { @@ -614,8 +610,8 @@ impl TestClient { ) { let (other_client, other_cx) = user; - self.app_state - .channel_store + cx_self + .read(ChannelStore::global) .update(cx_self, |channel_store, cx| { channel_store.invite_member(channel, other_client.user_id().unwrap(), true, cx) }) @@ -624,11 +620,10 @@ impl TestClient { cx_self.foreground().run_until_parked(); - other_client - .app_state - .channel_store - .update(other_cx, |channels, _| { - channels.respond_to_channel_invite(channel, true) + other_cx + .read(ChannelStore::global) + .update(other_cx, |channel_store, _| { + channel_store.respond_to_channel_invite(channel, true) }) .await .unwrap(); diff --git a/crates/collab_ui/src/channel_view.rs b/crates/collab_ui/src/channel_view.rs index a95576805074d63a5a74de8d1d107899cb956714..b2e65eb2fa1bd5e92ddf5436115b938958f1383e 100644 --- a/crates/collab_ui/src/channel_view.rs +++ b/crates/collab_ui/src/channel_view.rs @@ -73,7 +73,7 @@ impl ChannelView { ) -> Task>> { let workspace = workspace.read(cx); let project = workspace.project().to_owned(); - let channel_store = workspace.app_state().channel_store.clone(); + let channel_store = ChannelStore::global(cx); let markdown = workspace .app_state() .languages diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index b446521c5ab6120840ec311425171d0dc231e1f3..1a17b48f19c303d9cd26915ff331c2fcc340cc89 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -81,7 +81,7 @@ impl ChatPanel { pub fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> ViewHandle { let fs = workspace.app_state().fs.clone(); let client = workspace.app_state().client.clone(); - let channel_store = workspace.app_state().channel_store.clone(); + let channel_store = ChannelStore::global(cx); let languages = workspace.app_state().languages.clone(); let input_editor = cx.add_view(|cx| { diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 951c8bf70ca647644943b3804f45cc6646eb395b..9e09abbd6a0d56fb711913c750dfaf06ae4547a3 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -648,7 +648,7 @@ impl CollabPanel { channel_editing_state: None, selection: None, user_store: workspace.user_store().clone(), - channel_store: workspace.app_state().channel_store.clone(), + channel_store: ChannelStore::global(cx), project: workspace.project().clone(), subscriptions: Vec::default(), match_candidates: Vec::default(), diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 41c86e538de466825115359d8bffcec816c06d8c..d1240a45cea5ced287514da3569ae4a782f36883 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -22,7 +22,6 @@ test-support = [ db = { path = "../db" } call = { path = "../call" } client = { path = "../client" } -channel = { path = "../channel" } collections = { path = "../collections" } context_menu = { path = "../context_menu" } drag_and_drop = { path = "../drag_and_drop" } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 6496d8134975509cb197be8320e1341430762c3b..d39c1cce762415253c6b2521b6583d7fe55cbd9c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -12,7 +12,6 @@ mod workspace_settings; use anyhow::{anyhow, Context, Result}; use call::ActiveCall; -use channel::ChannelStore; use client::{ proto::{self, PeerId}, Client, TypedEnvelope, UserStore, @@ -450,7 +449,6 @@ pub struct AppState { pub languages: Arc, pub client: Arc, pub user_store: ModelHandle, - pub channel_store: ModelHandle, pub workspace_store: ModelHandle, pub fs: Arc, pub build_window_options: @@ -487,8 +485,6 @@ impl AppState { let http_client = util::http::FakeHttpClient::with_404_response(); let client = Client::new(http_client.clone(), cx); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http_client, cx)); - let channel_store = - cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx)); theme::init((), cx); @@ -500,7 +496,7 @@ impl AppState { fs, languages, user_store, - channel_store, + // channel_store, workspace_store, initialize_workspace: |_, _, _, _| Task::ready(Ok(())), build_window_options: |_, _, _| Default::default(), @@ -3527,15 +3523,12 @@ impl Workspace { let client = project.read(cx).client(); let user_store = project.read(cx).user_store(); - let channel_store = - cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx)); let app_state = Arc::new(AppState { languages: project.read(cx).languages().clone(), workspace_store, client, user_store, - channel_store, fs: project.read(cx).fs().clone(), build_window_options: |_, _, _| Default::default(), initialize_workspace: |_, _, _, _| Task::ready(Ok(())), diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 12ae0f2ffce9709b5b9c45cb2b28053c5bf1f355..6c8d3218505b729a860e06b2a8be220c9f70f25e 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -3,7 +3,6 @@ use anyhow::{anyhow, Context, Result}; use backtrace::Backtrace; -use channel::ChannelStore; use cli::{ ipc::{self, IpcSender}, CliRequest, CliResponse, IpcHandshake, FORCE_CLI_MODE_ENV_VAR_NAME, @@ -138,8 +137,6 @@ fn main() { languages::init(languages.clone(), node_runtime.clone(), cx); let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx)); - let channel_store = - cx.add_model(|cx| ChannelStore::new(client.clone(), user_store.clone(), cx)); let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx)); cx.set_global(client.clone()); @@ -156,7 +153,7 @@ fn main() { outline::init(cx); project_symbols::init(cx); project_panel::init(Assets, cx); - channel::init(&client); + channel::init(&client, user_store.clone(), cx); diagnostics::init(cx); search::init(cx); semantic_index::init(fs.clone(), http.clone(), languages.clone(), cx); @@ -184,7 +181,6 @@ fn main() { languages, client: client.clone(), user_store, - channel_store, fs, build_window_options, initialize_workspace, diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index ce9b7e32a3f1aee0339a6a055f9c2579e49cdfb0..4e9a34c2699ab977eca0ed07b4784cc52f55922d 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -2424,6 +2424,7 @@ mod tests { state.build_window_options = build_window_options; theme::init((), cx); audio::init((), cx); + channel::init(&app_state.client, app_state.user_store.clone(), cx); call::init(app_state.client.clone(), app_state.user_store.clone(), cx); workspace::init(app_state.clone(), cx); Project::init_settings(cx);