From bb01e85fd6ce340808c26adad9e40d1d62a9482d Mon Sep 17 00:00:00 2001 From: Neon Date: Wed, 4 Dec 2024 11:41:10 +0800 Subject: [PATCH] delete zed modification --- scripts/zed-intergration/.gitignore | 1 - scripts/zed-intergration/README.md | 26 - scripts/zed-intergration/build.sh | 43 - ...1-add-new-module-mega-and-mega_panel.patch | 262 ------ ...-integrate-basic-panel-code-with-zed.patch | 581 ------------ ...-add-mega-panel-trait-implementation.patch | 162 ---- .../0004-fix-make-mega_panel-runnable.patch | 87 -- ...panel-very-basic-info-render-support.patch | 185 ---- .../0006-mega-basic-rest-api-support.patch | 228 ----- ...-control-pad-and-information-display.patch | 350 -------- .../0008-mega-feat-toggle-fuse-mount.patch | 579 ------------ ...-Fix-dont-restore-previous-workspace.patch | 254 ------ .../0010-Fix-checkout-in-project_panel.patch | 242 ----- ...0011-Add-basic-mega-rest-api-support.patch | 835 ----------------- .../patches/0012-fix-api-call-logic.patch | 611 ------------- .../0013-fix-features-wrongly-opened.patch | 35 - .../0014-fix-checkout-in-context-menu.patch | 207 ----- .../0015-fix-reading-mega-settings.patch | 221 ----- ...-heartbeat-to-detect-if-fuse-running.patch | 240 ----- .../patches/0017-add-commit-button.patch | 846 ------------------ .../0018-adjust-context-menu-for-fuse.patch | 104 --- .../patches/0019-fix-warnings.patch | 164 ---- ...crate-collab-compile-error-with-mega.patch | 82 -- ...code-quality-format-and-fix-warnings.patch | 401 --------- .../0022-improve-context-button-display.patch | 592 ------------ ...isplay-checkout-points-in-mega_panel.patch | 135 --- ...c-when-failed-to-start-fuse-manually.patch | 107 --- 27 files changed, 7580 deletions(-) delete mode 100644 scripts/zed-intergration/.gitignore delete mode 100644 scripts/zed-intergration/README.md delete mode 100755 scripts/zed-intergration/build.sh delete mode 100644 scripts/zed-intergration/patches/0001-add-new-module-mega-and-mega_panel.patch delete mode 100644 scripts/zed-intergration/patches/0002-mega-integrate-basic-panel-code-with-zed.patch delete mode 100644 scripts/zed-intergration/patches/0003-add-mega-panel-trait-implementation.patch delete mode 100644 scripts/zed-intergration/patches/0004-fix-make-mega_panel-runnable.patch delete mode 100644 scripts/zed-intergration/patches/0005-mega_panel-very-basic-info-render-support.patch delete mode 100644 scripts/zed-intergration/patches/0006-mega-basic-rest-api-support.patch delete mode 100644 scripts/zed-intergration/patches/0007-mega_panel-control-pad-and-information-display.patch delete mode 100644 scripts/zed-intergration/patches/0008-mega-feat-toggle-fuse-mount.patch delete mode 100644 scripts/zed-intergration/patches/0009-Fix-dont-restore-previous-workspace.patch delete mode 100644 scripts/zed-intergration/patches/0010-Fix-checkout-in-project_panel.patch delete mode 100644 scripts/zed-intergration/patches/0011-Add-basic-mega-rest-api-support.patch delete mode 100644 scripts/zed-intergration/patches/0012-fix-api-call-logic.patch delete mode 100644 scripts/zed-intergration/patches/0013-fix-features-wrongly-opened.patch delete mode 100644 scripts/zed-intergration/patches/0014-fix-checkout-in-context-menu.patch delete mode 100644 scripts/zed-intergration/patches/0015-fix-reading-mega-settings.patch delete mode 100644 scripts/zed-intergration/patches/0016-add-heartbeat-to-detect-if-fuse-running.patch delete mode 100644 scripts/zed-intergration/patches/0017-add-commit-button.patch delete mode 100644 scripts/zed-intergration/patches/0018-adjust-context-menu-for-fuse.patch delete mode 100644 scripts/zed-intergration/patches/0019-fix-warnings.patch delete mode 100644 scripts/zed-intergration/patches/0020-fix-crate-collab-compile-error-with-mega.patch delete mode 100644 scripts/zed-intergration/patches/0021-improve-code-quality-format-and-fix-warnings.patch delete mode 100644 scripts/zed-intergration/patches/0022-improve-context-button-display.patch delete mode 100644 scripts/zed-intergration/patches/0023-display-checkout-points-in-mega_panel.patch delete mode 100644 scripts/zed-intergration/patches/0024-don-t-panic-when-failed-to-start-fuse-manually.patch diff --git a/scripts/zed-intergration/.gitignore b/scripts/zed-intergration/.gitignore deleted file mode 100644 index 18d402992..000000000 --- a/scripts/zed-intergration/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/zed/ diff --git a/scripts/zed-intergration/README.md b/scripts/zed-intergration/README.md deleted file mode 100644 index 6c4c95eb7..000000000 --- a/scripts/zed-intergration/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Intro -We use a patched version of zed to help with the data edition in the monorepo that mega managing. - -# How to use -Currently, the script for patching and building zed is only used for helping making up the docker image. - -However, you can still use the script or manually build the patched version of zed. - -## With unix-shell environment - -Simply execute the script and you shall get the target binary right in the: -```shell -# build the patched zed -./build.sh - -# run zed -./zed/target/release/zed -``` - -## Without unix-shell environment - -You can still follow the steps below to build: -- Clone zed -- Checkout to the specific version mentioned in `build.sh` -- Use the patches in `./patches/` with `git am xxx.patch` -- Run `cargo build -r` and enjoy:) diff --git a/scripts/zed-intergration/build.sh b/scripts/zed-intergration/build.sh deleted file mode 100755 index f2a9a48a0..000000000 --- a/scripts/zed-intergration/build.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/sh - -# Clone zed and switch to the specific version -ZED_ROOT='./zed' -ZED_REPO='https://github.com/zed-industries/zed.git' -TARGET_PATCH_VERSION='a56f946a7d0734839f820d2943dabe7fa09a4b22' - -# Place patch files here -PATCH_DIR='./patches/' - -COUNTDOWN=10 -export MEGA_ROOT="`pwd`/../.." - -# Initialize or update zed repository -git clone ${ZED_REPO} ${ZED_ROOT} -cd ${ZED_ROOT} -git fetch - -# Check & Cleanup -if ! git diff --quiet; then - count=1 - echo "You have uncomitted changes, all the change will be resotred in $COUNTDOWN seconds!" - while [ $count -le $COUNTDOWN ]; do - sleep 1 - echo "Restoring in $(( $COUNTDOWN - $count )), press Ctrl-C to exit..." - ((count++)) - done - git restore . -fi - -# Patch -git checkout ${TARGET_PATCH_VERSION} -for patch in ../patches/*.patch; do - echo "Applying: $patch" - git am "$patch" - if [ $? -ne 0 ]; then - echo "Failed applying patch: $patch" - exit 1 - fi -done - -# Build -cargo build --release diff --git a/scripts/zed-intergration/patches/0001-add-new-module-mega-and-mega_panel.patch b/scripts/zed-intergration/patches/0001-add-new-module-mega-and-mega_panel.patch deleted file mode 100644 index c5ebff0e2..000000000 --- a/scripts/zed-intergration/patches/0001-add-new-module-mega-and-mega_panel.patch +++ /dev/null @@ -1,262 +0,0 @@ -From 006bd0e01b5deba6792af824a5a73c32e96efa2c Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sat, 19 Oct 2024 21:24:00 +0800 -Subject: [PATCH 01/24] add new module mega and mega_panel - ---- - Cargo.lock | 23 ++++++ - Cargo.toml | 4 + - crates/mega/LICENSE-GPL | 1 + - crates/mega/src/delegate.rs | 0 - crates/mega_panel/LICENSE-GPL | 1 + - crates/mega_panel/src/mega_panel_settings.rs | 80 ++++++++++++++++++++ - crates/zed/Cargo.toml | 1 + - crates/zed/src/zed.rs | 12 +++ - 8 files changed, 122 insertions(+) - create mode 120000 crates/mega/LICENSE-GPL - create mode 100644 crates/mega/src/delegate.rs - create mode 120000 crates/mega_panel/LICENSE-GPL - create mode 100644 crates/mega_panel/src/mega_panel_settings.rs - -diff --git a/Cargo.lock b/Cargo.lock -index 6f1d7b2c9c..d39aae09ee 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6884,6 +6884,28 @@ dependencies = [ - "objc", - ] - -+[[package]] -+name = "mega" -+version = "0.1.0" -+dependencies = [ -+ "reqwest 0.12.8", -+ "serde", -+] -+ -+[[package]] -+name = "mega_panel" -+version = "0.1.0" -+dependencies = [ -+ "anyhow", -+ "editor", -+ "file_icons", -+ "gpui", -+ "schemars", -+ "serde", -+ "settings", -+ "workspace", -+] -+ - [[package]] - name = "memchr" - version = "2.7.4" -@@ -14631,6 +14653,7 @@ dependencies = [ - "libc", - "log", - "markdown_preview", -+ "mega_panel", - "menu", - "mimalloc", - "nix", -diff --git a/Cargo.toml b/Cargo.toml -index 4a4ddb4424..6a02b98478 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -64,6 +64,8 @@ members = [ - "crates/markdown", - "crates/markdown_preview", - "crates/media", -+ "crates/mega", -+ "crates/mega_panel", - "crates/menu", - "crates/multi_buffer", - "crates/node_runtime", -@@ -240,6 +242,8 @@ lsp = { path = "crates/lsp" } - markdown = { path = "crates/markdown" } - markdown_preview = { path = "crates/markdown_preview" } - media = { path = "crates/media" } -+mega = { path = "crates/mega" } -+mega_panel = { path = "crates/mega_panel" } - menu = { path = "crates/menu" } - multi_buffer = { path = "crates/multi_buffer" } - node_runtime = { path = "crates/node_runtime" } -diff --git a/crates/mega/LICENSE-GPL b/crates/mega/LICENSE-GPL -new file mode 120000 -index 0000000000..89e542f750 ---- /dev/null -+++ b/crates/mega/LICENSE-GPL -@@ -0,0 +1 @@ -+../../LICENSE-GPL -\ No newline at end of file -diff --git a/crates/mega/src/delegate.rs b/crates/mega/src/delegate.rs -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/crates/mega_panel/LICENSE-GPL b/crates/mega_panel/LICENSE-GPL -new file mode 120000 -index 0000000000..89e542f750 ---- /dev/null -+++ b/crates/mega_panel/LICENSE-GPL -@@ -0,0 +1 @@ -+../../LICENSE-GPL -\ No newline at end of file -diff --git a/crates/mega_panel/src/mega_panel_settings.rs b/crates/mega_panel/src/mega_panel_settings.rs -new file mode 100644 -index 0000000000..1ca1149b01 ---- /dev/null -+++ b/crates/mega_panel/src/mega_panel_settings.rs -@@ -0,0 +1,80 @@ -+use schemars::JsonSchema; -+use gpui::Pixels; -+use gpui::private::serde::{Deserialize, Serialize}; -+use settings::{Settings, SettingsSources}; -+ -+#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Copy, PartialEq)] -+#[serde(rename_all = "snake_case")] -+pub enum MegaPanelDockPosition { -+ Left, -+ Right, -+} -+ -+#[derive(Deserialize, Debug, Clone, Copy, PartialEq)] -+pub struct MegaPanelSettings { -+ pub button: bool, -+ pub default_width: Pixels, -+ pub dock: MegaPanelDockPosition, -+ pub file_icons: bool, -+ pub folder_icons: bool, -+ pub git_status: bool, -+ pub indent_size: f32, -+ pub auto_reveal_entries: bool, -+ pub auto_fold_dirs: bool, -+} -+ -+#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] -+pub struct MegaPanelSettingsContent { -+ /// Whether to show the outline panel button in the status bar. -+ /// -+ /// Default: true -+ pub button: Option, -+ /// Customize default width (in pixels) taken by outline panel -+ /// -+ /// Default: 240 -+ pub default_width: Option, -+ /// The position of outline panel -+ /// -+ /// Default: left -+ pub dock: Option, -+ /// Whether to show file icons in the outline panel. -+ /// -+ /// Default: true -+ pub file_icons: Option, -+ /// Whether to show folder icons or chevrons for directories in the outline panel. -+ /// -+ /// Default: true -+ pub folder_icons: Option, -+ /// Whether to show the git status in the outline panel. -+ /// -+ /// Default: true -+ pub git_status: Option, -+ /// Amount of indentation (in pixels) for nested items. -+ /// -+ /// Default: 20 -+ pub indent_size: Option, -+ /// Whether to reveal it in the outline panel automatically, -+ /// when a corresponding project entry becomes active. -+ /// Gitignored entries are never auto revealed. -+ /// -+ /// Default: true -+ pub auto_reveal_entries: Option, -+ /// Whether to fold directories automatically -+ /// when directory has only one directory inside. -+ /// -+ /// Default: true -+ pub auto_fold_dirs: Option, -+} -+ -+impl Settings for MegaPanelSettings { -+ const KEY: Option<&'static str> = Some("outline_panel"); -+ -+ type FileContent = MegaPanelSettingsContent; -+ -+ fn load( -+ sources: SettingsSources, -+ _: &mut gpui::AppContext, -+ ) -> anyhow::Result { -+ sources.json_merge() -+ } -+} -\ No newline at end of file -diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml -index 69ca3aa98d..81243cf62f 100644 ---- a/crates/zed/Cargo.toml -+++ b/crates/zed/Cargo.toml -@@ -66,6 +66,7 @@ languages = { workspace = true, features = ["load-grammars"] } - libc.workspace = true - log.workspace = true - markdown_preview.workspace = true -+mega_panel.workspace = true - menu.workspace = true - mimalloc = { version = "0.1", optional = true } - nix = { workspace = true, features = ["pthread", "signal"] } -diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs -index c33cef4a4b..545e42551a 100644 ---- a/crates/zed/src/zed.rs -+++ b/crates/zed/src/zed.rs -@@ -27,6 +27,7 @@ use anyhow::Context as _; - use assets::Assets; - use futures::{channel::mpsc, select_biased, StreamExt}; - use outline_panel::OutlinePanel; -+use mega_panel::MegaPanel; - use project::Item; - use project_panel::ProjectPanel; - use quick_action_bar::QuickActionBar; -@@ -238,6 +239,7 @@ pub fn initialize_workspace( - - let project_panel = ProjectPanel::load(workspace_handle.clone(), cx.clone()); - let outline_panel = OutlinePanel::load(workspace_handle.clone(), cx.clone()); -+ let mega_panel = MegaPanel::load(workspace_handle.clone(), cx.clone()); - let terminal_panel = TerminalPanel::load(workspace_handle.clone(), cx.clone()); - let channels_panel = - collab_ui::collab_panel::CollabPanel::load(workspace_handle.clone(), cx.clone()); -@@ -250,6 +252,7 @@ pub fn initialize_workspace( - - let ( - project_panel, -+ mega_panel, - outline_panel, - terminal_panel, - assistant_panel, -@@ -258,6 +261,7 @@ pub fn initialize_workspace( - notification_panel, - ) = futures::try_join!( - project_panel, -+ mega_panel, - outline_panel, - terminal_panel, - assistant_panel, -@@ -269,6 +273,7 @@ pub fn initialize_workspace( - workspace_handle.update(&mut cx, |workspace, cx| { - workspace.add_panel(assistant_panel, cx); - workspace.add_panel(project_panel, cx); -+ workspace.add_panel(mega_panel, cx); - workspace.add_panel(outline_panel, cx); - workspace.add_panel(terminal_panel, cx); - workspace.add_panel(channels_panel, cx); -@@ -467,6 +472,13 @@ pub fn initialize_workspace( - workspace.toggle_panel_focus::(cx); - }, - ) -+ .register_action( -+ |workspace: &mut Workspace, -+ _: &mega_panel::ToggleFocus, -+ cx: &mut ViewContext| { -+ workspace.toggle_panel_focus::(cx); -+ }, -+ ) - .register_action( - |workspace: &mut Workspace, - _: &outline_panel::ToggleFocus, --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0002-mega-integrate-basic-panel-code-with-zed.patch b/scripts/zed-intergration/patches/0002-mega-integrate-basic-panel-code-with-zed.patch deleted file mode 100644 index 97bf4f9f6..000000000 --- a/scripts/zed-intergration/patches/0002-mega-integrate-basic-panel-code-with-zed.patch +++ /dev/null @@ -1,581 +0,0 @@ -From afca3aee776df6674d0c6d17858d944c64ec56ae Mon Sep 17 00:00:00 2001 -From: Neon -Date: Mon, 21 Oct 2024 09:18:40 +0800 -Subject: [PATCH 02/24] mega: integrate basic panel code with zed - ---- - Cargo.lock | 7 +- - crates/mega/Cargo.toml | 18 ++ - crates/mega/src/fuse.rs | 0 - crates/mega/src/mega.rs | 52 +++++ - crates/mega_panel/Cargo.toml | 24 +++ - crates/mega_panel/src/mega_panel.rs | 195 +++++++++++++++++++ - crates/mega_panel/src/mega_panel_settings.rs | 41 +--- - crates/workspace/Cargo.toml | 1 + - crates/workspace/src/workspace.rs | 10 +- - crates/zed/Cargo.toml | 1 + - crates/zed/src/main.rs | 6 +- - 11 files changed, 315 insertions(+), 40 deletions(-) - create mode 100644 crates/mega/Cargo.toml - create mode 100644 crates/mega/src/fuse.rs - create mode 100644 crates/mega/src/mega.rs - create mode 100644 crates/mega_panel/Cargo.toml - create mode 100644 crates/mega_panel/src/mega_panel.rs - -diff --git a/Cargo.lock b/Cargo.lock -index d39aae09ee..6503eb5359 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6888,6 +6888,7 @@ dependencies = [ - name = "mega" - version = "0.1.0" - dependencies = [ -+ "gpui", - "reqwest 0.12.8", - "serde", - ] -@@ -6897,12 +6898,14 @@ name = "mega_panel" - version = "0.1.0" - dependencies = [ - "anyhow", -- "editor", -+ "db", - "file_icons", - "gpui", -+ "mega", - "schemars", - "serde", - "settings", -+ "util", - "workspace", - ] - -@@ -14314,6 +14317,7 @@ dependencies = [ - "itertools 0.13.0", - "language", - "log", -+ "mega", - "node_runtime", - "parking_lot", - "postage", -@@ -14653,6 +14657,7 @@ dependencies = [ - "libc", - "log", - "markdown_preview", -+ "mega", - "mega_panel", - "menu", - "mimalloc", -diff --git a/crates/mega/Cargo.toml b/crates/mega/Cargo.toml -new file mode 100644 -index 0000000000..dec6093220 ---- /dev/null -+++ b/crates/mega/Cargo.toml -@@ -0,0 +1,18 @@ -+[package] -+name = "mega" -+version = "0.1.0" -+edition = "2021" -+publish = false -+license = "GPL-3.0-or-later" -+ -+[lints] -+workspace = true -+ -+[lib] -+path = 'src/mega.rs' -+ -+[dependencies] -+gpui.workspace = true -+ -+reqwest.workspace = true -+serde.workspace = true -diff --git a/crates/mega/src/fuse.rs b/crates/mega/src/fuse.rs -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -new file mode 100644 -index 0000000000..4b51004907 ---- /dev/null -+++ b/crates/mega/src/mega.rs -@@ -0,0 +1,52 @@ -+// This crate delegate mega and its fuse daemon. -+// The following requirements should be met: -+// -+// TODO: -+// 1. Only one daemon on this machine. -+// 2. At least one daemon on this machine when zed startup. -+// 3. Complete docs. -+ -+use std::sync::Arc; -+use gpui::{AppContext, Context, EventEmitter, Model, ModelContext}; -+ -+mod delegate; -+mod fuse; -+ -+pub fn init(cx: &mut AppContext) { -+ // let reservation = cx.reserve_model(); -+ // cx.insert_model(reservation, |cx| { -+ // cx.new_model(|_cx| { Mega::new() }) -+ // }); -+} -+ -+#[derive(Clone, Debug, PartialEq)] -+pub enum Event {} -+pub struct Mega {} -+ -+pub struct MegaFuse {} -+ -+impl EventEmitter for Mega {} -+ -+ -+impl Mega { -+ pub fn init_settings(cx: &mut AppContext) { -+ -+ } -+ -+ pub fn init(cx: &mut AppContext) { -+ // let reservation = cx.reserve_model(); -+ // cx.insert_model(reservation, |cx| { -+ // cx.new_model(|_cx| { Mega::new() }) -+ // }); -+ } -+ -+ pub fn new(cx: &mut AppContext) -> Self { -+ Mega {} -+ } -+ -+ pub fn toggle_mega(&self) { todo!() } -+ -+ pub fn toggle_fuse(&self) { todo!() } -+ -+ pub fn checkout_path(&self) { todo!() } -+} -diff --git a/crates/mega_panel/Cargo.toml b/crates/mega_panel/Cargo.toml -new file mode 100644 -index 0000000000..9a8ae896a2 ---- /dev/null -+++ b/crates/mega_panel/Cargo.toml -@@ -0,0 +1,24 @@ -+[package] -+name = "mega_panel" -+version = "0.1.0" -+edition = "2021" -+publish = false -+license = "GPL-3.0-or-later" -+[lib] -+path = 'src/mega_panel.rs' -+ -+[lints] -+workspace = true -+ -+[dependencies] -+mega.workspace = true -+workspace.workspace = true -+gpui.workspace = true -+file_icons.workspace = true -+settings.workspace = true -+db.workspace = true -+util.workspace = true -+ -+anyhow.workspace = true -+serde.workspace = true -+schemars.workspace = true -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -new file mode 100644 -index 0000000000..7e38d88752 ---- /dev/null -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -0,0 +1,195 @@ -+use anyhow::{anyhow, Context}; -+use db::kvp::KEY_VALUE_STORE; -+use file_icons::FileIcons; -+use gpui::{actions, Action, AppContext, AssetSource, AsyncWindowContext, Entity, EventEmitter, FocusHandle, FocusableView, IntoElement, Model, Pixels, Render, Subscription, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext}; -+use gpui::private::serde_derive::{Deserialize, Serialize}; -+use gpui::private::serde_json; -+use mega::{Mega, MegaFuse}; -+use settings::{Settings, SettingsStore}; -+use util::{ResultExt, TryFutureExt}; -+use workspace::dock::{DockPosition, Panel, PanelEvent, PanelId}; -+use workspace::ui::IconName; -+use workspace::{Pane, Workspace}; -+use crate::mega_panel_settings::MegaPanelSettings; -+ -+mod mega_panel_settings; -+ -+const MEGA_PANEL_KEY: &str = "MegaPanel"; -+ -+actions!( -+ mega_panel, -+ [ -+ Open, -+ ToggleFocus, -+ ToggleFuseMount, -+ ] -+); -+ -+pub struct MegaPanel { -+ mega: WeakModel, -+ workspace: WeakView, -+ focus_handle: FocusHandle, -+ pending_serialization: Task>, -+ width: Option, -+} -+ -+#[derive(Serialize, Deserialize)] -+struct SerializedMegaPanel { -+ width: Option, -+} -+ -+#[derive(Debug)] -+pub enum Event { -+ Focus, -+} -+ -+pub fn init_settings(cx: &mut AppContext) { -+ MegaPanelSettings::register(cx); -+} -+ -+pub fn init(assets: impl AssetSource, cx: &mut AppContext) { -+ init_settings(cx); -+ file_icons::init(assets, cx); -+ -+ cx.observe_new_views(|workspace: &mut Workspace, _| { -+ workspace.register_action(|workspace, _: &ToggleFocus, cx| { -+ workspace.toggle_panel_focus::(cx); -+ }); -+ }) -+ .detach(); -+} -+ -+impl EventEmitter for MegaPanel {} -+ -+impl EventEmitter for MegaPanel {} -+ -+impl Render for MegaPanel { -+ fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { -+ todo!(); -+ "" -+ } -+} -+ -+impl FocusableView for MegaPanel { -+ fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { -+ self.focus_handle.clone() -+ } -+} -+ -+impl Panel for MegaPanel { -+ fn persistent_name() -> &'static str { -+ todo!() -+ } -+ -+ fn position(&self, cx: &WindowContext) -> DockPosition { -+ todo!() -+ } -+ -+ fn position_is_valid(&self, position: DockPosition) -> bool { -+ todo!() -+ } -+ -+ fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext) { -+ todo!() -+ } -+ -+ fn size(&self, cx: &WindowContext) -> Pixels { -+ todo!() -+ } -+ -+ fn set_size(&mut self, size: Option, cx: &mut ViewContext) { -+ todo!() -+ } -+ -+ fn icon(&self, cx: &WindowContext) -> Option { -+ todo!() -+ } -+ -+ fn icon_tooltip(&self, cx: &WindowContext) -> Option<&'static str> { -+ todo!() -+ } -+ -+ fn toggle_action(&self) -> Box { -+ todo!() -+ } -+} -+ -+impl MegaPanel { -+ pub async fn load( -+ workspace: WeakView, -+ mut cx: AsyncWindowContext, -+ ) -> anyhow::Result> { -+ let serialized_panel = cx -+ .background_executor() -+ .spawn(async move { KEY_VALUE_STORE.read_kvp(MEGA_PANEL_KEY) }) -+ .await -+ .map_err(|e| anyhow!("Failed to load mega panel: {}", e)) -+ .context("loading mega panel") -+ .log_err() -+ .flatten() -+ .map(|panel| serde_json::from_str::(&panel)) -+ .transpose() -+ .log_err() -+ .flatten(); -+ -+ workspace.update( -+ &mut cx, -+ |workspace, cx| { -+ let panel = MegaPanel::new(workspace, cx); -+ if let Some(serialized_panel) = serialized_panel { -+ panel.update(cx, |panel, cx| { -+ panel.width = serialized_panel.width.map(|px| px.round()); -+ cx.notify(); -+ }); -+ } -+ panel -+ } -+ ) -+ } -+ -+ fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { -+ let mega_panel = cx.new_view(|cx| { -+ let mega = workspace.mega(); -+ -+ let focus_handle = cx.focus_handle(); -+ cx.on_focus(&focus_handle, Self::focus_in).detach(); -+ -+ cx.subscribe(mega, |this, mega, event, cx| { -+ // TODO: listen for user operations -+ }).detach(); -+ -+ Self { -+ mega: mega.downgrade(), -+ workspace: workspace.weak_handle(), -+ focus_handle, -+ pending_serialization: Task::ready(None), -+ width: None, -+ -+ } -+ }); -+ -+ mega_panel -+ } -+ -+ fn serialize(&mut self, cx: &mut ViewContext) { -+ let width = self.width; -+ self.pending_serialization = cx.background_executor().spawn( -+ async move { -+ KEY_VALUE_STORE -+ .write_kvp( -+ MEGA_PANEL_KEY.into(), -+ serde_json::to_string(&SerializedMegaPanel { width })?, -+ ) -+ .await?; -+ anyhow::Ok(()) -+ } -+ .log_err(), -+ ); -+ } -+ -+ fn focus_in(&mut self, cx: &mut ViewContext) { -+ if !self.focus_handle.contains_focused(cx) { -+ cx.emit(Event::Focus); -+ } -+ } -+} -\ No newline at end of file -diff --git a/crates/mega_panel/src/mega_panel_settings.rs b/crates/mega_panel/src/mega_panel_settings.rs -index 1ca1149b01..bfd4b337d0 100644 ---- a/crates/mega_panel/src/mega_panel_settings.rs -+++ b/crates/mega_panel/src/mega_panel_settings.rs -@@ -15,59 +15,26 @@ pub struct MegaPanelSettings { - pub button: bool, - pub default_width: Pixels, - pub dock: MegaPanelDockPosition, -- pub file_icons: bool, -- pub folder_icons: bool, -- pub git_status: bool, -- pub indent_size: f32, -- pub auto_reveal_entries: bool, -- pub auto_fold_dirs: bool, - } - - #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] - pub struct MegaPanelSettingsContent { -- /// Whether to show the outline panel button in the status bar. -+ /// Whether to show the mega panel button in the status bar. - /// - /// Default: true - pub button: Option, -- /// Customize default width (in pixels) taken by outline panel -+ /// Customize default width (in pixels) taken by mega panel - /// - /// Default: 240 - pub default_width: Option, -- /// The position of outline panel -+ /// The position of mega panel - /// - /// Default: left - pub dock: Option, -- /// Whether to show file icons in the outline panel. -- /// -- /// Default: true -- pub file_icons: Option, -- /// Whether to show folder icons or chevrons for directories in the outline panel. -- /// -- /// Default: true -- pub folder_icons: Option, -- /// Whether to show the git status in the outline panel. -- /// -- /// Default: true -- pub git_status: Option, -- /// Amount of indentation (in pixels) for nested items. -- /// -- /// Default: 20 -- pub indent_size: Option, -- /// Whether to reveal it in the outline panel automatically, -- /// when a corresponding project entry becomes active. -- /// Gitignored entries are never auto revealed. -- /// -- /// Default: true -- pub auto_reveal_entries: Option, -- /// Whether to fold directories automatically -- /// when directory has only one directory inside. -- /// -- /// Default: true -- pub auto_fold_dirs: Option, - } - - impl Settings for MegaPanelSettings { -- const KEY: Option<&'static str> = Some("outline_panel"); -+ const KEY: Option<&'static str> = Some("mega_panel"); - - type FileContent = MegaPanelSettingsContent; - -diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml -index 47f6c138c8..83686bb100 100644 ---- a/crates/workspace/Cargo.toml -+++ b/crates/workspace/Cargo.toml -@@ -45,6 +45,7 @@ http_client.workspace = true - itertools.workspace = true - language.workspace = true - log.workspace = true -+mega.workspace = true - node_runtime.workspace = true - parking_lot.workspace = true - postage.workspace = true -diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs -index ec4079ba9f..af4f47e5d3 100644 ---- a/crates/workspace/src/workspace.rs -+++ b/crates/workspace/src/workspace.rs -@@ -97,6 +97,7 @@ use ui::{ - }; - use util::{maybe, ResultExt, TryFutureExt}; - use uuid::Uuid; -+use mega::Mega; - pub use workspace_settings::{ - AutosaveSetting, RestoreOnStartupBehavior, TabBarSettings, WorkspaceSettings, - }; -@@ -559,6 +560,7 @@ pub struct AppState { - pub build_window_options: fn(Option, &mut AppContext) -> WindowOptions, - pub node_runtime: NodeRuntime, - pub session: Model, -+ pub mega: Model, - } - - struct GlobalAppState(Weak); -@@ -609,7 +611,8 @@ impl AppState { - let session = cx.new_model(|cx| AppSession::new(Session::test(), cx)); - let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx)); - let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx)); -- -+ let mega = cx.new_model(|cx| { Mega::new(cx) }); -+ - theme::init(theme::LoadThemes::JustBase, cx); - client::init(&client, cx); - crate::init_settings(cx); -@@ -623,6 +626,7 @@ impl AppState { - node_runtime: NodeRuntime::unavailable(), - build_window_options: |_, _| Default::default(), - session, -+ mega, - }) - } - } -@@ -1266,6 +1270,8 @@ impl Workspace { - pub fn project(&self) -> &Model { - &self.project - } -+ -+ pub fn mega(&self) -> &Model { &self.app_state.mega } - - pub fn recent_navigation_history( - &self, -@@ -4426,6 +4432,7 @@ impl Workspace { - - let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx)); - let session = cx.new_model(|cx| AppSession::new(Session::test(), cx)); -+ let mega = cx.new_model(|cx| Mega::new(cx) ); - cx.activate_window(); - let app_state = Arc::new(AppState { - languages: project.read(cx).languages().clone(), -@@ -4436,6 +4443,7 @@ impl Workspace { - build_window_options: |_, _| Default::default(), - node_runtime: NodeRuntime::unavailable(), - session, -+ mega, - }); - let workspace = Self::new(Default::default(), project, app_state, cx); - workspace.active_pane.update(cx, |pane, cx| pane.focus(cx)); -diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml -index 81243cf62f..abc36527ec 100644 ---- a/crates/zed/Cargo.toml -+++ b/crates/zed/Cargo.toml -@@ -66,6 +66,7 @@ languages = { workspace = true, features = ["load-grammars"] } - libc.workspace = true - log.workspace = true - markdown_preview.workspace = true -+mega.workspace = true - mega_panel.workspace = true - menu.workspace = true - mimalloc = { version = "0.1", optional = true } -diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs -index 25baf74c68..3e3094ecb0 100644 ---- a/crates/zed/src/main.rs -+++ b/crates/zed/src/main.rs -@@ -53,6 +53,7 @@ use theme::{ActiveTheme, SystemAppearance, ThemeRegistry, ThemeSettings}; - use time::UtcOffset; - use util::{maybe, parse_env_output, ResultExt, TryFutureExt}; - use uuid::Uuid; -+use mega::Mega; - use welcome::{show_welcome_view, BaseKeymap, FIRST_OPEN}; - use workspace::{ - notifications::{simple_message_notification::MessageNotification, NotificationId}, -@@ -521,6 +522,7 @@ fn main() { - Client::set_global(client.clone(), cx); - - zed::init(cx); -+ mega::init(cx); - project::Project::init(&client, cx); - client::init(&client, cx); - language::init(cx); -@@ -548,7 +550,8 @@ fn main() { - } - } - let app_session = cx.new_model(|cx| AppSession::new(session, cx)); -- -+ let mega = cx.new_model(|cx| Mega::new(cx)); -+ - let app_state = Arc::new(AppState { - languages: languages.clone(), - client: client.clone(), -@@ -558,6 +561,7 @@ fn main() { - workspace_store, - node_runtime: node_runtime.clone(), - session: app_session, -+ mega, - }); - AppState::set_global(Arc::downgrade(&app_state), cx); - --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0003-add-mega-panel-trait-implementation.patch b/scripts/zed-intergration/patches/0003-add-mega-panel-trait-implementation.patch deleted file mode 100644 index 37eeefa16..000000000 --- a/scripts/zed-intergration/patches/0003-add-mega-panel-trait-implementation.patch +++ /dev/null @@ -1,162 +0,0 @@ -From a6636b00e11cfa284e2e152cb2ac0a6d92508a34 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Mon, 21 Oct 2024 09:33:24 +0800 -Subject: [PATCH 03/24] add: mega `panel` trait implementation - ---- - Cargo.lock | 1 + - crates/mega_panel/Cargo.toml | 1 + - crates/mega_panel/src/mega_panel.rs | 41 +++++++++++++++++------ - crates/project_panel/src/project_panel.rs | 8 ++--- - 4 files changed, 37 insertions(+), 14 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index 6503eb5359..80c72872e4 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6900,6 +6900,7 @@ dependencies = [ - "anyhow", - "db", - "file_icons", -+ "fs", - "gpui", - "mega", - "schemars", -diff --git a/crates/mega_panel/Cargo.toml b/crates/mega_panel/Cargo.toml -index 9a8ae896a2..d139d51f0d 100644 ---- a/crates/mega_panel/Cargo.toml -+++ b/crates/mega_panel/Cargo.toml -@@ -17,6 +17,7 @@ gpui.workspace = true - file_icons.workspace = true - settings.workspace = true - db.workspace = true -+fs.workspace = true - util.workspace = true - - anyhow.workspace = true -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 7e38d88752..e10ef55f0a 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -1,6 +1,8 @@ -+use std::sync::Arc; - use anyhow::{anyhow, Context}; - use db::kvp::KEY_VALUE_STORE; - use file_icons::FileIcons; -+use fs::Fs; - use gpui::{actions, Action, AppContext, AssetSource, AsyncWindowContext, Entity, EventEmitter, FocusHandle, FocusableView, IntoElement, Model, Pixels, Render, Subscription, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext}; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; -@@ -10,7 +12,7 @@ use util::{ResultExt, TryFutureExt}; - use workspace::dock::{DockPosition, Panel, PanelEvent, PanelId}; - use workspace::ui::IconName; - use workspace::{Pane, Workspace}; --use crate::mega_panel_settings::MegaPanelSettings; -+use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; - - mod mega_panel_settings; - -@@ -29,6 +31,7 @@ pub struct MegaPanel { - mega: WeakModel, - workspace: WeakView, - focus_handle: FocusHandle, -+ fs: Arc, - pending_serialization: Task>, - width: Option, - } -@@ -78,39 +81,57 @@ impl FocusableView for MegaPanel { - - impl Panel for MegaPanel { - fn persistent_name() -> &'static str { -- todo!() -+ "Mega Panel" - } - - fn position(&self, cx: &WindowContext) -> DockPosition { -- todo!() -+ match MegaPanelSettings::get_global(cx).dock { -+ MegaPanelDockPosition::Left => DockPosition::Left, -+ MegaPanelDockPosition::Right => DockPosition::Right, -+ } - } - - fn position_is_valid(&self, position: DockPosition) -> bool { -- todo!() -+ matches!(position, DockPosition::Left | DockPosition::Right) - } - - fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext) { -- todo!() -+ settings::update_settings_file::( -+ self.fs.clone(), -+ cx, -+ move |settings, _| { -+ let dock = match position { -+ DockPosition::Left | DockPosition::Bottom => MegaPanelDockPosition::Left, -+ DockPosition::Right => MegaPanelDockPosition::Right, -+ }; -+ settings.dock = Some(dock); -+ }, -+ ); - } - - fn size(&self, cx: &WindowContext) -> Pixels { -- todo!() -+ self.width -+ .unwrap_or_else(|| MegaPanelSettings::get_global(cx).default_width) - } - - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { -- todo!() -+ self.width = size; -+ self.serialize(cx); -+ cx.notify(); - } - - fn icon(&self, cx: &WindowContext) -> Option { -- todo!() -+ MegaPanelSettings::get_global(cx) -+ .button -+ .then_some(IconName::FileGit) - } - - fn icon_tooltip(&self, cx: &WindowContext) -> Option<&'static str> { -- todo!() -+ Some("Mega Panel") - } - - fn toggle_action(&self) -> Box { -- todo!() -+ Box::new(ToggleFocus) - } - } - -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index 08a0ef4b40..c4fb39f587 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -3060,6 +3060,10 @@ impl EventEmitter for ProjectPanel {} - impl EventEmitter for ProjectPanel {} - - impl Panel for ProjectPanel { -+ fn persistent_name() -> &'static str { -+ "Project Panel" -+ } -+ - fn position(&self, cx: &WindowContext) -> DockPosition { - match ProjectPanelSettings::get_global(cx).dock { - ProjectPanelDockPosition::Left => DockPosition::Left, -@@ -3110,10 +3114,6 @@ impl Panel for ProjectPanel { - Box::new(ToggleFocus) - } - -- fn persistent_name() -> &'static str { -- "Project Panel" -- } -- - fn starts_open(&self, cx: &WindowContext) -> bool { - let project = &self.project.read(cx); - project.dev_server_project_id().is_some() --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0004-fix-make-mega_panel-runnable.patch b/scripts/zed-intergration/patches/0004-fix-make-mega_panel-runnable.patch deleted file mode 100644 index a010f21cf..000000000 --- a/scripts/zed-intergration/patches/0004-fix-make-mega_panel-runnable.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 5e676b9b1669d078a25bcee9a0d1b87743862a30 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Mon, 21 Oct 2024 10:00:36 +0800 -Subject: [PATCH 04/24] fix: make mega_panel runnable - ---- - assets/settings/default.json | 8 ++++++++ - crates/mega_panel/src/mega_panel.rs | 8 ++++---- - crates/zed/src/main.rs | 1 + - 3 files changed, 13 insertions(+), 4 deletions(-) - -diff --git a/assets/settings/default.json b/assets/settings/default.json -index 4bde5ee174..147f80a12b 100644 ---- a/assets/settings/default.json -+++ b/assets/settings/default.json -@@ -371,6 +371,14 @@ - "show": null - } - }, -+ "mega_panel": { -+ // Whether to show the mega panel button in the status bar -+ "button": true, -+ // Default width of the mega panel. -+ "default_width": 240, -+ // Where to dock the mega panel. Can be 'left' or 'right'. -+ "dock": "left", -+ }, - "outline_panel": { - // Whether to show the outline panel button in the status bar - "button": true, -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index e10ef55f0a..03c41f06ad 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -10,7 +10,7 @@ use mega::{Mega, MegaFuse}; - use settings::{Settings, SettingsStore}; - use util::{ResultExt, TryFutureExt}; - use workspace::dock::{DockPosition, Panel, PanelEvent, PanelId}; --use workspace::ui::IconName; -+use workspace::ui::{v_flex, IconName}; - use workspace::{Pane, Workspace}; - use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; - -@@ -52,6 +52,7 @@ pub fn init_settings(cx: &mut AppContext) { - - pub fn init(assets: impl AssetSource, cx: &mut AppContext) { - init_settings(cx); -+ println!("Mega settings should be registered"); - file_icons::init(assets, cx); - - cx.observe_new_views(|workspace: &mut Workspace, _| { -@@ -68,8 +69,7 @@ impl EventEmitter for MegaPanel {} - - impl Render for MegaPanel { - fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { -- todo!(); -- "" -+ v_flex() - } - } - -@@ -183,9 +183,9 @@ impl MegaPanel { - mega: mega.downgrade(), - workspace: workspace.weak_handle(), - focus_handle, -+ fs: workspace.app_state().fs.clone(), - pending_serialization: Task::ready(None), - width: None, -- - } - }); - -diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs -index 3e3094ecb0..005d086f48 100644 ---- a/crates/zed/src/main.rs -+++ b/crates/zed/src/main.rs -@@ -257,6 +257,7 @@ fn init_ui( - outline::init(cx); - project_symbols::init(cx); - project_panel::init(Assets, cx); -+ mega_panel::init(Assets, cx); - outline_panel::init(Assets, cx); - tasks_ui::init(cx); - snippets_ui::init(cx); --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0005-mega_panel-very-basic-info-render-support.patch b/scripts/zed-intergration/patches/0005-mega_panel-very-basic-info-render-support.patch deleted file mode 100644 index 45f5ccb31..000000000 --- a/scripts/zed-intergration/patches/0005-mega_panel-very-basic-info-render-support.patch +++ /dev/null @@ -1,185 +0,0 @@ -From e04d4b01af7991ed4b40fcd9553f20e67f2ec53f Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 22 Oct 2024 16:15:01 +0800 -Subject: [PATCH 05/24] mega_panel: very basic info render support - ---- - Cargo.lock | 4 +- - crates/mega_panel/Cargo.toml | 2 + - crates/mega_panel/src/mega_panel.rs | 61 +++++++++++++++++++++++++---- - 3 files changed, 58 insertions(+), 9 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index 80c72872e4..0474f53d0a 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6889,7 +6889,7 @@ name = "mega" - version = "0.1.0" - dependencies = [ - "gpui", -- "reqwest 0.12.8", -+ "reqwest_client", - "serde", - ] - -@@ -6906,8 +6906,10 @@ dependencies = [ - "schemars", - "serde", - "settings", -+ "text", - "util", - "workspace", -+ "worktree", - ] - - [[package]] -diff --git a/crates/mega_panel/Cargo.toml b/crates/mega_panel/Cargo.toml -index d139d51f0d..2238a405c1 100644 ---- a/crates/mega_panel/Cargo.toml -+++ b/crates/mega_panel/Cargo.toml -@@ -13,11 +13,13 @@ workspace = true - [dependencies] - mega.workspace = true - workspace.workspace = true -+worktree.workspace = true - gpui.workspace = true - file_icons.workspace = true - settings.workspace = true - db.workspace = true - fs.workspace = true -+text.workspace = true - util.workspace = true - - anyhow.workspace = true -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 03c41f06ad..b055d76fcf 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -3,15 +3,17 @@ use anyhow::{anyhow, Context}; - use db::kvp::KEY_VALUE_STORE; - use file_icons::FileIcons; - use fs::Fs; --use gpui::{actions, Action, AppContext, AssetSource, AsyncWindowContext, Entity, EventEmitter, FocusHandle, FocusableView, IntoElement, Model, Pixels, Render, Subscription, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext}; -+use gpui::{actions, anchored, deferred, div, impl_actions, px, uniform_list, Action, AnyElement, AppContext, AssetSource, AsyncWindowContext, ClipboardItem, DismissEvent, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, HighlightStyle, InteractiveElement, IntoElement, KeyContext, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, Render, SharedString, Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext}; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; - use mega::{Mega, MegaFuse}; - use settings::{Settings, SettingsStore}; -+use text::BufferId; - use util::{ResultExt, TryFutureExt}; - use workspace::dock::{DockPosition, Panel, PanelEvent, PanelId}; --use workspace::ui::{v_flex, IconName}; -+use workspace::ui::{v_flex, IconName, Label, LabelCommon, LabelSize}; - use workspace::{Pane, Workspace}; -+use worktree::{Entry, ProjectEntryId, WorktreeId}; - use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; - - mod mega_panel_settings; -@@ -21,18 +23,18 @@ const MEGA_PANEL_KEY: &str = "MegaPanel"; - actions!( - mega_panel, - [ -- Open, - ToggleFocus, - ToggleFuseMount, -+ CheckoutPath, - ] - ); - - pub struct MegaPanel { -- mega: WeakModel, -+ mega_handle: WeakModel, - workspace: WeakView, - focus_handle: FocusHandle, - fs: Arc, -- pending_serialization: Task>, -+ pending_serialization: Task>, // TODO check how to use it - width: Option, - } - -@@ -41,6 +43,12 @@ struct SerializedMegaPanel { - width: Option, - } - -+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -+enum MegaEntry { -+ Dir(WorktreeId, ProjectEntryId), -+ File(WorktreeId, BufferId), -+} -+ - #[derive(Debug)] - pub enum Event { - Focus, -@@ -52,7 +60,6 @@ pub fn init_settings(cx: &mut AppContext) { - - pub fn init(assets: impl AssetSource, cx: &mut AppContext) { - init_settings(cx); -- println!("Mega settings should be registered"); - file_icons::init(assets, cx); - - cx.observe_new_views(|workspace: &mut Workspace, _| { -@@ -69,7 +76,27 @@ impl EventEmitter for MegaPanel {} - - impl Render for MegaPanel { - fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { -- v_flex() -+ let mega_panel = v_flex() -+ .id("mega_panel") -+ .size_full() -+ .relative() -+ .on_action(cx.listener(Self::toggle_fuse_mount)) -+ .on_action(cx.listener(Self::checkout_path)) -+ .track_focus(&self.focus_handle) -+ .gap_6() -+ .p_4() -+ .child( -+ Label::new("Mega Control Panel") -+ .single_line() -+ .weight(FontWeight::BOLD) -+ .size(LabelSize::Large) -+ ) -+ .gap_4() -+ .p_4() -+ .child(self.render_status_panel(cx)) -+ .child(self.render_control_panel(cx)); -+ -+ mega_panel - } - } - -@@ -180,7 +207,7 @@ impl MegaPanel { - }).detach(); - - Self { -- mega: mega.downgrade(), -+ mega_handle: mega.downgrade(), - workspace: workspace.weak_handle(), - focus_handle, - fs: workspace.app_state().fs.clone(), -@@ -213,4 +240,22 @@ impl MegaPanel { - cx.emit(Event::Focus); - } - } -+ -+ pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { -+ // let mega = self.mega_handle.upgrade() -+ // .unwrap_or_else() -+ todo!() -+ } -+ -+ pub fn checkout_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { -+ todo!() -+ } -+ -+ fn render_status_panel(&mut self, cx: &mut ViewContext) -> Div { -+ v_flex().child(Label::new("I am a status panel")) -+ } -+ -+ fn render_control_panel(&mut self, cx: &mut ViewContext) -> Div { -+ v_flex().child(Label::new("I am a control panel")) -+ } - } -\ No newline at end of file --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0006-mega-basic-rest-api-support.patch b/scripts/zed-intergration/patches/0006-mega-basic-rest-api-support.patch deleted file mode 100644 index b1981ec2e..000000000 --- a/scripts/zed-intergration/patches/0006-mega-basic-rest-api-support.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 8b57a9f693c95e92ee5299ff30b6cd791c08da71 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 22 Oct 2024 19:12:08 +0800 -Subject: [PATCH 06/24] mega: basic rest api support - ---- - Cargo.lock | 1 + - crates/mega/Cargo.toml | 3 +- - crates/mega/src/delegate.rs | 58 ++++++++++++++++++++ - crates/mega/src/mega.rs | 84 ++++++++++++++++++++++++++--- - crates/mega_panel/src/mega_panel.rs | 1 + - 5 files changed, 139 insertions(+), 8 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index 0474f53d0a..1ffec64d85 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6888,6 +6888,7 @@ dependencies = [ - name = "mega" - version = "0.1.0" - dependencies = [ -+ "bytes 0.4.12", - "gpui", - "reqwest_client", - "serde", -diff --git a/crates/mega/Cargo.toml b/crates/mega/Cargo.toml -index dec6093220..1572c73b90 100644 ---- a/crates/mega/Cargo.toml -+++ b/crates/mega/Cargo.toml -@@ -13,6 +13,7 @@ path = 'src/mega.rs' - - [dependencies] - gpui.workspace = true -+reqwest_client.workspace = true - --reqwest.workspace = true - serde.workspace = true -+bytes = "0.4.12" -diff --git a/crates/mega/src/delegate.rs b/crates/mega/src/delegate.rs -index e69de29bb2..c767060048 100644 ---- a/crates/mega/src/delegate.rs -+++ b/crates/mega/src/delegate.rs -@@ -0,0 +1,58 @@ -+use serde::{Deserialize, Serialize}; -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub(crate) struct MountRequest { -+ pub(crate) path: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct MountResponse { -+ status: String, -+ mount: MountInfo, -+ message: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct MountInfo { -+ hash: String, -+ path: String, -+ inode: u64, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct MountsResponse { -+ status: String, -+ mounts: Vec, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct UmountRequest { -+ path: Option, -+ inode: Option, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct UmountResponse { -+ status: String, -+ message: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct ConfigResponse { -+ status: String, -+ config: ConfigInfo, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct ConfigInfo { -+ mega_url: String, -+ mount_path: String, -+ store_path: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+struct ConfigRequest { -+ mega_url: Option, -+ mount_path: Option, -+ store_path: Option, -+} -\ No newline at end of file -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 4b51004907..f24e2d9e5d 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -6,8 +6,10 @@ - // 2. At least one daemon on this machine when zed startup. - // 3. Complete docs. - --use std::sync::Arc; --use gpui::{AppContext, Context, EventEmitter, Model, ModelContext}; -+use gpui::http_client::{AsyncBody, HttpClient}; -+use gpui::{AppContext, Context, EventEmitter, WindowContext}; -+use reqwest_client::ReqwestClient; -+use serde::Serialize; - - mod delegate; - mod fuse; -@@ -21,7 +23,10 @@ pub fn init(cx: &mut AppContext) { - - #[derive(Clone, Debug, PartialEq)] - pub enum Event {} --pub struct Mega {} -+pub struct Mega { -+ mega_running: bool, -+ fuse_running: bool, -+} - - pub struct MegaFuse {} - -@@ -41,12 +46,77 @@ impl Mega { - } - - pub fn new(cx: &mut AppContext) -> Self { -- Mega {} -+ Mega { -+ fuse_running: false, -+ mega_running: false, -+ } - } - -- pub fn toggle_mega(&self) { todo!() } -+ pub fn toggle_mega(&self, cx: &mut WindowContext) { todo!() } - -- pub fn toggle_fuse(&self) { todo!() } -+ pub fn toggle_fuse(&self, cx: &mut WindowContext) { todo!() } -+ -+ pub fn toggle_mount(&self, cx: &mut WindowContext) { -+ // let req_body = delegate::MountRequest { -+ // path: "".parse().unwrap() -+ // }; -+ -+ cx.spawn(|_cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.get( -+ "localhost:2725/api/fs/mount", -+ AsyncBody::empty(), -+ false -+ ).await; -+ }).detach(); -+ } - -- pub fn checkout_path(&self) { todo!() } -+ pub fn checkout_path(&self, cx: &mut WindowContext) { -+ cx.spawn(|_cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.get( -+ "localhost:2725/api/fs/mount", -+ AsyncBody::empty(), -+ false -+ ).await; -+ }).detach(); -+ } -+ -+ pub fn get_fuse_config(&self, cx: &mut WindowContext) { -+ cx.spawn(|_cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.get( -+ "localhost:2725/api/fs/mount", -+ AsyncBody::empty(), -+ false -+ ).await; -+ }).detach(); -+ } -+ -+ pub fn set_fuse_config(&self, cx: &mut WindowContext) { -+ cx.spawn(|_cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.post_json( -+ "localhost:2725/api/config", -+ AsyncBody::empty(), -+ ).await; -+ }).detach(); -+ } -+ -+ pub fn get_fuse_mpoint(&self, cx: &mut WindowContext) { -+ cx.spawn(|_cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.get( -+ "localhost:2725/api/config", -+ AsyncBody::empty(), -+ false -+ ).await; -+ }).detach(); -+ } -+ -+} -+ -+#[cfg(test)] -+mod test { -+ - } -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index b055d76fcf..76ac003f31 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -244,6 +244,7 @@ impl MegaPanel { - pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { - // let mega = self.mega_handle.upgrade() - // .unwrap_or_else() -+ - todo!() - } - --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0007-mega_panel-control-pad-and-information-display.patch b/scripts/zed-intergration/patches/0007-mega_panel-control-pad-and-information-display.patch deleted file mode 100644 index 0b0062e84..000000000 --- a/scripts/zed-intergration/patches/0007-mega_panel-control-pad-and-information-display.patch +++ /dev/null @@ -1,350 +0,0 @@ -From 0ae6bfb40025aca376878982579a322eaa231143 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sat, 26 Oct 2024 22:02:19 +0800 -Subject: [PATCH 07/24] mega_panel: control pad and information display - ---- - crates/mega/src/mega.rs | 56 ++++++++--- - crates/mega_panel/src/mega_panel.rs | 150 +++++++++++++++++++++------- - 2 files changed, 154 insertions(+), 52 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index f24e2d9e5d..4bf4aa27d6 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -6,8 +6,9 @@ - // 2. At least one daemon on this machine when zed startup. - // 3. Complete docs. - -+use std::path::{Path, PathBuf}; - use gpui::http_client::{AsyncBody, HttpClient}; --use gpui::{AppContext, Context, EventEmitter, WindowContext}; -+use gpui::{AppContext, Context, EntityId, EventEmitter, ModelContext, WindowContext}; - use reqwest_client::ReqwestClient; - use serde::Serialize; - -@@ -22,10 +23,18 @@ pub fn init(cx: &mut AppContext) { - } - - #[derive(Clone, Debug, PartialEq)] --pub enum Event {} -+pub enum Event { -+ MegaRunning(bool), -+ FuseRunning(bool), -+ FuseMounted(bool), -+} - pub struct Mega { - mega_running: bool, - fuse_running: bool, -+ fuse_mounted: bool, -+ -+ checkout_path: Option, -+ panel_id: Option, - } - - pub struct MegaFuse {} -@@ -49,19 +58,36 @@ impl Mega { - Mega { - fuse_running: false, - mega_running: false, -+ fuse_mounted: false, -+ checkout_path: None, -+ panel_id: None, - } -- } -+ } - -- pub fn toggle_mega(&self, cx: &mut WindowContext) { todo!() } -+ pub fn update_status(&mut self, cx: &mut ModelContext) { -+ if let None = self.panel_id { -+ return; -+ } -+ -+ cx.notify(); -+ } - -- pub fn toggle_fuse(&self, cx: &mut WindowContext) { todo!() } -+ pub fn status(&self) -> (bool, bool, bool) { -+ (self.mega_running, self.fuse_running, self.fuse_mounted) -+ } -+ -+ pub fn toggle_mega(&self, cx: &mut ModelContext) { todo!() } -+ -+ pub fn toggle_fuse(&self, cx: &mut ModelContext) { -+ -+ } - -- pub fn toggle_mount(&self, cx: &mut WindowContext) { -+ pub fn toggle_mount(&self, cx: &mut ModelContext) { - // let req_body = delegate::MountRequest { - // path: "".parse().unwrap() - // }; - -- cx.spawn(|_cx| async { -+ cx.spawn(|_this, _cx| async { - let client = ReqwestClient::new(); - let req = client.get( - "localhost:2725/api/fs/mount", -@@ -71,8 +97,8 @@ impl Mega { - }).detach(); - } - -- pub fn checkout_path(&self, cx: &mut WindowContext) { -- cx.spawn(|_cx| async { -+ pub fn checkout_path(&self, cx: &mut ModelContext) { -+ cx.spawn(|_this, _cx| async { - let client = ReqwestClient::new(); - let req = client.get( - "localhost:2725/api/fs/mount", -@@ -82,8 +108,8 @@ impl Mega { - }).detach(); - } - -- pub fn get_fuse_config(&self, cx: &mut WindowContext) { -- cx.spawn(|_cx| async { -+ pub fn get_fuse_config(&self, cx: &mut ModelContext) { -+ cx.spawn(|_this, _cx| async { - let client = ReqwestClient::new(); - let req = client.get( - "localhost:2725/api/fs/mount", -@@ -93,8 +119,8 @@ impl Mega { - }).detach(); - } - -- pub fn set_fuse_config(&self, cx: &mut WindowContext) { -- cx.spawn(|_cx| async { -+ pub fn set_fuse_config(&self, cx: &mut ModelContext) { -+ cx.spawn(|_this, _cx| async { - let client = ReqwestClient::new(); - let req = client.post_json( - "localhost:2725/api/config", -@@ -103,8 +129,8 @@ impl Mega { - }).detach(); - } - -- pub fn get_fuse_mpoint(&self, cx: &mut WindowContext) { -- cx.spawn(|_cx| async { -+ pub fn get_fuse_mpoint(&self, cx: &mut ModelContext) { -+ cx.spawn(|_this, _cx| async { - let client = ReqwestClient::new(); - let req = client.get( - "localhost:2725/api/config", -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 76ac003f31..80a26cf4c2 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -1,20 +1,19 @@ --use std::sync::Arc; -+use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; - use anyhow::{anyhow, Context}; - use db::kvp::KEY_VALUE_STORE; --use file_icons::FileIcons; - use fs::Fs; --use gpui::{actions, anchored, deferred, div, impl_actions, px, uniform_list, Action, AnyElement, AppContext, AssetSource, AsyncWindowContext, ClipboardItem, DismissEvent, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, HighlightStyle, InteractiveElement, IntoElement, KeyContext, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, Render, SharedString, Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WindowContext}; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; --use mega::{Mega, MegaFuse}; --use settings::{Settings, SettingsStore}; -+use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext}; -+use mega::Mega; -+use settings::Settings; -+use std::sync::Arc; - use text::BufferId; - use util::{ResultExt, TryFutureExt}; --use workspace::dock::{DockPosition, Panel, PanelEvent, PanelId}; --use workspace::ui::{v_flex, IconName, Label, LabelCommon, LabelSize}; --use workspace::{Pane, Workspace}; --use worktree::{Entry, ProjectEntryId, WorktreeId}; --use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; -+use workspace::dock::{DockPosition, Panel, PanelEvent}; -+use workspace::ui::{h_flex, v_flex, Button, Clickable, Color, FixedWidth, IconName, IconPosition, Label, LabelCommon, LabelSize, StyledExt, StyledTypography}; -+use workspace::Workspace; -+use worktree::{ProjectEntryId, WorktreeId}; - - mod mega_panel_settings; - -@@ -30,9 +29,10 @@ actions!( - ); - - pub struct MegaPanel { -- mega_handle: WeakModel, -+ mega_handle: Model, - workspace: WeakView, - focus_handle: FocusHandle, -+ scroll_handle: UniformListScrollHandle, - fs: Arc, - pending_serialization: Task>, // TODO check how to use it - width: Option, -@@ -86,16 +86,17 @@ impl Render for MegaPanel { - .gap_6() - .p_4() - .child( -- Label::new("Mega Control Panel") -- .single_line() -- .weight(FontWeight::BOLD) -- .size(LabelSize::Large) -+ h_flex().justify_center().child( -+ Label::new("Mega Control Panel") -+ .single_line() -+ .weight(FontWeight::BOLD) -+ .size(LabelSize::Large)) - ) -- .gap_4() -- .p_4() -- .child(self.render_status_panel(cx)) -- .child(self.render_control_panel(cx)); -- -+ .child(horizontal_separator(cx)) -+ .child(self.render_status(cx)) -+ .child(horizontal_separator(cx)) -+ .child(self.render_buttons(cx)); -+ - mega_panel - } - } -@@ -191,25 +192,26 @@ impl MegaPanel { - }); - } - panel -- } -+ }, - ) - } - - fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { - let mega_panel = cx.new_view(|cx| { - let mega = workspace.mega(); -- -+ - let focus_handle = cx.focus_handle(); - cx.on_focus(&focus_handle, Self::focus_in).detach(); -- -+ - cx.subscribe(mega, |this, mega, event, cx| { -- // TODO: listen for user operations -+ // TODO: listen for mega events - }).detach(); -- -+ - Self { -- mega_handle: mega.downgrade(), -+ mega_handle: mega.clone(), - workspace: workspace.weak_handle(), - focus_handle, -+ scroll_handle: UniformListScrollHandle::new(), - fs: workspace.app_state().fs.clone(), - pending_serialization: Task::ready(None), - width: None, -@@ -240,23 +242,97 @@ impl MegaPanel { - cx.emit(Event::Focus); - } - } -- -+ - pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { - // let mega = self.mega_handle.upgrade() - // .unwrap_or_else() -- -- todo!() -+ -+ self.warn_unimplemented(cx); - } -- -+ - pub fn checkout_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { -- todo!() -+ self.warn_unimplemented(cx); - } -- -- fn render_status_panel(&mut self, cx: &mut ViewContext) -> Div { -- v_flex().child(Label::new("I am a status panel")) -+ -+ fn render_status(&mut self, cx: &mut ViewContext) -> Div { -+ let ( -+ mega_running, -+ fuse_running, -+ fuse_mounted -+ ) = self.mega_handle.read(cx).status(); -+ -+ v_flex() -+ .gap_1() -+ .children([ -+ self.status_unit(cx, "Mega Backend:", mega_running), -+ self.status_unit(cx, "Scorpio Backend:", fuse_running), -+ self.status_unit(cx, "Fuse Mounted:", fuse_mounted), -+ ]) - } -- -- fn render_control_panel(&mut self, cx: &mut ViewContext) -> Div { -- v_flex().child(Label::new("I am a control panel")) -+ -+ fn render_buttons(&mut self, cx: &mut ViewContext) -> impl IntoElement { -+ -+ fn encap_btn(btn: Button) -> Div { -+ div() -+ .m_1() -+ .border_1() -+ .child(btn) -+ } -+ -+ v_flex() -+ .id("mega-control-pad") -+ .size_full() -+ .children([ -+ encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio") -+ .full_width() -+ .icon(IconName::Plus) -+ .icon_position(IconPosition::Start) -+ .on_click(cx.listener(|this, _, cx| { -+ this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); -+ })) -+ ), -+ encap_btn(Button::new("btn_toggle_mount", "Toggle Mount") -+ .full_width() -+ .icon(IconName::Context) -+ .icon_position(IconPosition::Start) -+ .on_click(cx.listener(|this, _, cx| { -+ this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -+ })) -+ ), -+ encap_btn(Button::new("btn_checkout", "Checkout Path") -+ .full_width() -+ .icon(IconName::Check) -+ .icon_position(IconPosition::Start) -+ .on_click(cx.listener(|this, _, cx| { -+ // TODO: should get the path here -+ this.mega_handle.update(cx, |mega, cx| mega.checkout_path(cx)); -+ })) -+ ), -+ ]) - } -+ -+ fn status_unit(&self, cx: &mut ViewContext, name: &'static str, state: bool) -> Stateful
{ -+ let unit_id = ElementId::from(SharedString::from(format!("status_{}", name.clone()))); -+ div() -+ .text_ui(cx) -+ .id(unit_id) -+ .child( -+ h_flex() -+ .justify_between() -+ .child(Label::new(name)) -+ .child(match state { -+ true => Label::new("Active").color(Color::Success), -+ false => Label::new("Inactive").color(Color::Error) -+ }) -+ ) -+ } -+ -+ fn warn_unimplemented(&self, cx: &mut ViewContext) { -+ let message = String::from("This operation is not implemented yet"); -+ let _ = cx.prompt(PromptLevel::Warning, "Unimplemented", Some(&message), &["Got it"]); -+ } -+} -+ -+fn horizontal_separator(cx: &mut WindowContext) -> Div { -+ div().mx_2().border_primary(cx).border_t_1() - } -\ No newline at end of file --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0008-mega-feat-toggle-fuse-mount.patch b/scripts/zed-intergration/patches/0008-mega-feat-toggle-fuse-mount.patch deleted file mode 100644 index dbcd35266..000000000 --- a/scripts/zed-intergration/patches/0008-mega-feat-toggle-fuse-mount.patch +++ /dev/null @@ -1,579 +0,0 @@ -From 8f8d3a30a45fa4f3b2359060d63a51f065c327d9 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 29 Oct 2024 18:50:39 +0800 -Subject: [PATCH 08/24] mega: feat toggle fuse mount - ---- - Cargo.lock | 6 +- - assets/settings/default.json | 12 +++ - crates/mega/Cargo.toml | 5 +- - crates/mega/src/mega.rs | 116 +++++++++++++--------- - crates/mega/src/mega_settings.rs | 50 ++++++++++ - crates/mega_panel/src/mega_panel.rs | 66 +++++++++--- - crates/project_panel/Cargo.toml | 1 + - crates/project_panel/src/project_panel.rs | 31 ++++++ - crates/zed/src/main.rs | 3 +- - 9 files changed, 225 insertions(+), 65 deletions(-) - create mode 100644 crates/mega/src/mega_settings.rs - -diff --git a/Cargo.lock b/Cargo.lock -index 1ffec64d85..c25acea09d 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6888,10 +6888,13 @@ dependencies = [ - name = "mega" - version = "0.1.0" - dependencies = [ -- "bytes 0.4.12", -+ "anyhow", -+ "bytes 1.7.2", - "gpui", - "reqwest_client", -+ "schemars", - "serde", -+ "settings", - ] - - [[package]] -@@ -8521,6 +8524,7 @@ dependencies = [ - "gpui", - "indexmap 1.9.3", - "language", -+ "mega", - "menu", - "pretty_assertions", - "project", -diff --git a/assets/settings/default.json b/assets/settings/default.json -index 147f80a12b..6ea0fff594 100644 ---- a/assets/settings/default.json -+++ b/assets/settings/default.json -@@ -379,6 +379,18 @@ - // Where to dock the mega panel. Can be 'left' or 'right'. - "dock": "left", - }, -+ "mega": { -+ // Url to communicate with mega -+ "mega_url": "http://localhost:8000", -+ // Url to communicate with fuse -+ "fuse_url": "http://localhost:2725", -+ // Default mount point for fuse -+ "mount_point": "/home/neon/projects", -+ // Path for mega executable -+ "mega_executable": "mega", -+ // Path for fuse executable -+ "fuse_executable": "scorpio" -+ }, - "outline_panel": { - // Whether to show the outline panel button in the status bar - "button": true, -diff --git a/crates/mega/Cargo.toml b/crates/mega/Cargo.toml -index 1572c73b90..658ed87476 100644 ---- a/crates/mega/Cargo.toml -+++ b/crates/mega/Cargo.toml -@@ -14,6 +14,9 @@ path = 'src/mega.rs' - [dependencies] - gpui.workspace = true - reqwest_client.workspace = true -+settings.workspace = true - - serde.workspace = true --bytes = "0.4.12" -+bytes.workspace = true -+schemars.workspace = true -+anyhow.workspace = true -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 4bf4aa27d6..84314de815 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -2,39 +2,46 @@ - // The following requirements should be met: - // - // TODO: --// 1. Only one daemon on this machine. -+// 1. Only one daemon on this machine. -+// This should be both warrantied by this module and scorpio - // 2. At least one daemon on this machine when zed startup. - // 3. Complete docs. -+// 4. Add settings for this module - - use std::path::{Path, PathBuf}; -+use std::sync::Arc; - use gpui::http_client::{AsyncBody, HttpClient}; --use gpui::{AppContext, Context, EntityId, EventEmitter, ModelContext, WindowContext}; -+use gpui::{AppContext, Context, EntityId, EventEmitter, ModelContext, SharedString, WindowContext}; - use reqwest_client::ReqwestClient; - use serde::Serialize; -+use settings::Settings; -+use crate::mega_settings::MegaSettings; - - mod delegate; - mod fuse; -+mod mega_settings; - - pub fn init(cx: &mut AppContext) { -- // let reservation = cx.reserve_model(); -- // cx.insert_model(reservation, |cx| { -- // cx.new_model(|_cx| { Mega::new() }) -- // }); -+ Mega::init(cx); - } - - #[derive(Clone, Debug, PartialEq)] - pub enum Event { - MegaRunning(bool), - FuseRunning(bool), -- FuseMounted(bool), -+ FuseMounted(Option), -+ FuseCheckout(Option), - } - pub struct Mega { - mega_running: bool, - fuse_running: bool, - fuse_mounted: bool, - -+ mount_point: Option, - checkout_path: Option, -- panel_id: Option, -+ -+ mega_url: String, -+ fuse_url: String, - } - - pub struct MegaFuse {} -@@ -43,69 +50,93 @@ impl EventEmitter for Mega {} - - - impl Mega { -- pub fn init_settings(cx: &mut AppContext) { -- -- } -+ pub fn init_settings(cx: &mut AppContext) { MegaSettings::register(cx); } - - pub fn init(cx: &mut AppContext) { -- // let reservation = cx.reserve_model(); -- // cx.insert_model(reservation, |cx| { -- // cx.new_model(|_cx| { Mega::new() }) -- // }); -+ Self::init_settings(cx); - } - - pub fn new(cx: &mut AppContext) -> Self { -+ let mount_point = PathBuf::from(MegaSettings::get_global(cx).mount_point.clone()); -+ let mega_url = MegaSettings::get_global(cx).mega_url.clone(); -+ let fuse_url = MegaSettings::get_global(cx).fuse_url.clone(); -+ - Mega { - fuse_running: false, - mega_running: false, - fuse_mounted: false, -+ -+ mount_point: None, - checkout_path: None, -- panel_id: None, -+ -+ mega_url, -+ fuse_url, - } - } -- -+ - pub fn update_status(&mut self, cx: &mut ModelContext) { -- if let None = self.panel_id { -- return; -- } -+ -+ - - cx.notify(); - } -- -+ - pub fn status(&self) -> (bool, bool, bool) { - (self.mega_running, self.fuse_running, self.fuse_mounted) - } - -- pub fn toggle_mega(&self, cx: &mut ModelContext) { todo!() } -+ pub fn toggle_mega(&mut self, cx: &mut ModelContext) { -+ self.mega_running = !self.mega_running; -+ cx.emit(Event::MegaRunning(self.mega_running)); -+ } - -- pub fn toggle_fuse(&self, cx: &mut ModelContext) { -- -+ pub fn toggle_fuse(&mut self, cx: &mut ModelContext) { -+ self.fuse_running = !self.fuse_running; -+ cx.emit(Event::FuseRunning(self.fuse_running)); - } - -- pub fn toggle_mount(&self, cx: &mut ModelContext) { -+ pub fn toggle_mount(&mut self, cx: &mut ModelContext) { - // let req_body = delegate::MountRequest { - // path: "".parse().unwrap() - // }; -- -- cx.spawn(|_this, _cx| async { -+ -+ cx.spawn(|this, mut cx| async move { - let client = ReqwestClient::new(); - let req = client.get( - "localhost:2725/api/fs/mount", - AsyncBody::empty(), - false - ).await; -+ -+ if let Some(mega) = this.upgrade() { -+ let _ = mega.update(&mut cx, |this, cx| { -+ if this.fuse_mounted { -+ this.fuse_mounted = false; -+ } else { -+ // FIXME just pretending that we've got something from fuse response -+ this.fuse_mounted = true; -+ this.mount_point = Some(PathBuf::from("/home/neon/projects")); -+ } -+ cx.emit(Event::FuseMounted(this.mount_point.clone())); -+ }); -+ } - }).detach(); - } - -- pub fn checkout_path(&self, cx: &mut ModelContext) { -- cx.spawn(|_this, _cx| async { -- let client = ReqwestClient::new(); -- let req = client.get( -- "localhost:2725/api/fs/mount", -- AsyncBody::empty(), -- false -- ).await; -- }).detach(); -+ pub fn checkout_path(&mut self, cx: &mut ModelContext) { -+ // for now, we assume there's only one path being checkout at a time. -+ if self.checkout_path.is_none() { -+ cx.spawn(|_this, _cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.get( -+ "localhost:2725/api/fs/mount", -+ AsyncBody::empty(), -+ false -+ ).await; -+ }).detach(); -+ } -+ -+ - } - - pub fn get_fuse_config(&self, cx: &mut ModelContext) { -@@ -128,18 +159,7 @@ impl Mega { - ).await; - }).detach(); - } -- -- pub fn get_fuse_mpoint(&self, cx: &mut ModelContext) { -- cx.spawn(|_this, _cx| async { -- let client = ReqwestClient::new(); -- let req = client.get( -- "localhost:2725/api/config", -- AsyncBody::empty(), -- false -- ).await; -- }).detach(); -- } -- -+ - } - - #[cfg(test)] -diff --git a/crates/mega/src/mega_settings.rs b/crates/mega/src/mega_settings.rs -new file mode 100644 -index 0000000000..82721208a1 ---- /dev/null -+++ b/crates/mega/src/mega_settings.rs -@@ -0,0 +1,50 @@ -+use std::path::PathBuf; -+use schemars::JsonSchema; -+use gpui::private::serde_derive::{Deserialize, Serialize}; -+use settings::{Settings, SettingsSources}; -+ -+#[derive(Default, Deserialize, Debug, Clone, PartialEq)] -+pub struct MegaSettings { -+ pub mega_url: String, -+ pub fuse_url: String, -+ pub mount_point: PathBuf, -+ pub mega_executable: PathBuf, -+ pub fuse_executable: PathBuf, -+} -+ -+#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] -+pub struct MegaSettingsContent { -+ /// Url to communicate with mega -+ /// -+ /// Default: http://localhost:8000 -+ pub mega_url: String, -+ /// Url to communicate with fuse -+ /// -+ /// Default: http://localhost:2725 -+ pub fuse_url: String, -+ /// Default mount point for fuse -+ /// -+ /// Default: "/" (for now) -+ pub mount_point: PathBuf, -+ /// Path for mega executable -+ /// -+ /// Default: "mega" (for now) -+ pub mega_executable: PathBuf, -+ /// Path for fuse executable -+ /// -+ /// Default: "scorpio" (for now) -+ pub fuse_executable: PathBuf, -+} -+ -+impl Settings for MegaSettings { -+ const KEY: Option<&'static str> = Some("mega"); -+ -+ type FileContent = MegaSettingsContent; -+ -+ fn load( -+ sources: SettingsSources, -+ _: &mut gpui::AppContext, -+ ) -> anyhow::Result { -+ sources.json_merge() -+ } -+} -\ No newline at end of file -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 80a26cf4c2..82e6047244 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -1,10 +1,11 @@ -+use std::path::PathBuf; - use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; - use anyhow::{anyhow, Context}; - use db::kvp::KEY_VALUE_STORE; - use fs::Fs; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; --use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext}; -+use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement, PathPromptOptions, Pixels, PromptLevel, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext}; - use mega::Mega; - use settings::Settings; - use std::sync::Arc; -@@ -154,7 +155,7 @@ impl Panel for MegaPanel { - .then_some(IconName::FileGit) - } - -- fn icon_tooltip(&self, cx: &WindowContext) -> Option<&'static str> { -+ fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> { - Some("Mega Panel") - } - -@@ -203,6 +204,7 @@ impl MegaPanel { - let focus_handle = cx.focus_handle(); - cx.on_focus(&focus_handle, Self::focus_in).detach(); - -+ #[allow(unused)] - cx.subscribe(mega, |this, mega, event, cx| { - // TODO: listen for mega events - }).detach(); -@@ -243,16 +245,22 @@ impl MegaPanel { - } - } - -- pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { -- // let mega = self.mega_handle.upgrade() -- // .unwrap_or_else() -- -- self.warn_unimplemented(cx); -- } -- - pub fn checkout_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { - self.warn_unimplemented(cx); - } -+ -+ pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { -+ // if let Some(workspace) = self.workspace.upgrade() { -+ // workspace.model.update(cx, |this, mx| { -+ // -+ // }); -+ // } -+ -+ self.mega_handle.update(cx, |this, cx | { -+ this.toggle_mount(cx); -+ -+ }); -+ } - - fn render_status(&mut self, cx: &mut ViewContext) -> Div { - let ( -@@ -283,12 +291,22 @@ impl MegaPanel { - .id("mega-control-pad") - .size_full() - .children([ -+ encap_btn(Button::new("btn_toggle_mega", "Toggle Mega") -+ .full_width() -+ .icon(IconName::Plus) -+ .icon_position(IconPosition::Start) -+ .on_click(cx.listener(|this, _, cx| { -+ this.mega_handle.update(cx, |mega, cx| mega.toggle_mega(cx)); -+ this.warn_unimplemented(cx); -+ })) -+ ), - encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio") - .full_width() - .icon(IconName::Plus) - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); -+ this.warn_unimplemented(cx); - })) - ), - encap_btn(Button::new("btn_toggle_mount", "Toggle Mount") -@@ -297,6 +315,9 @@ impl MegaPanel { - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -+ -+ -+ this.warn_unimplemented(cx); - })) - ), - encap_btn(Button::new("btn_checkout", "Checkout Path") -@@ -304,15 +325,34 @@ impl MegaPanel { - .icon(IconName::Check) - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { -- // TODO: should get the path here -- this.mega_handle.update(cx, |mega, cx| mega.checkout_path(cx)); -+ this.warn_unimplemented(cx); -+ // TODO: should read the path here -+ let options = PathPromptOptions { -+ files: true, -+ directories: true, -+ multiple: false, -+ }; -+ -+ let abs_path = cx.prompt_for_paths(options); -+ // if let Some(workspace_view) = this.workspace.upgrade() { -+ // let mut workspace = workspace_view.read(cx); -+ // workspace.open_workspace_for_paths(false, vec![], cx); -+ // } -+ cx.spawn(|this, mut cx| async move { -+ let Ok(Ok(Some(result))) = abs_path.await else { -+ return; -+ }; -+ -+ -+ }).detach(); -+ // mega.update(cx, |mega, cx| mega.checkout_path(cx)); - })) - ), - ]) - } - - fn status_unit(&self, cx: &mut ViewContext, name: &'static str, state: bool) -> Stateful
{ -- let unit_id = ElementId::from(SharedString::from(format!("status_{}", name.clone()))); -+ let unit_id = ElementId::from(SharedString::from(format!("status_{}", name))); - div() - .text_ui(cx) - .id(unit_id) -@@ -328,7 +368,7 @@ impl MegaPanel { - } - - fn warn_unimplemented(&self, cx: &mut ViewContext) { -- let message = String::from("This operation is not implemented yet"); -+ let message = String::from("This operation is not implemented yet, functions may not behave correctly"); - let _ = cx.prompt(PromptLevel::Warning, "Unimplemented", Some(&message), &["Got it"]); - } - } -diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml -index 11c7364e58..cc9e0ba8f6 100644 ---- a/crates/project_panel/Cargo.toml -+++ b/crates/project_panel/Cargo.toml -@@ -21,6 +21,7 @@ file_icons.workspace = true - indexmap.workspace = true - git.workspace = true - gpui.workspace = true -+mega.workspace = true - menu.workspace = true - pretty_assertions.workspace = true - project.workspace = true -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index c4fb39f587..34f3bf0f54 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -43,6 +43,7 @@ use std::{ - sync::Arc, - time::Duration, - }; -+use db::write_and_log; - use theme::ThemeSettings; - use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem, Tooltip}; - use util::{maybe, ResultExt, TryFutureExt}; -@@ -223,6 +224,7 @@ struct DraggedProjectEntryView { - impl ProjectPanel { - fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { - let project = workspace.project().clone(); -+ let mega = workspace.mega().clone(); - let project_panel = cx.new_view(|cx: &mut ViewContext| { - let focus_handle = cx.focus_handle(); - cx.on_focus(&focus_handle, Self::focus_in).detach(); -@@ -282,6 +284,34 @@ impl ProjectPanel { - ) - .detach(); - -+ cx.subscribe(&mega, |this, mega, mega_event, cx| match mega_event { -+ mega::Event::FuseMounted(Some(path)) => { -+ let path = path.to_owned(); -+ this.workspace -+ .update(cx, |workspace, cx| { -+ cx.spawn(|this, mut cx| async move { -+ if let Some(task) = this -+ .update(&mut cx, |this, cx| { -+ this.open_workspace_for_paths(false, vec!(path), cx) -+ }) -+ .log_err() -+ { -+ task.await.log_err(); -+ } -+ }) -+ .detach() -+ }) -+ .log_err(); -+ -+ -+ } -+ mega::Event::FuseCheckout(path) => { -+ // FIXME: impl it. -+ println!("Fuse Checkout NOT implemented in project for now!"); -+ } -+ _ => {} -+ }).detach(); -+ - cx.observe_global::(|_, cx| { - cx.notify(); - }) -@@ -491,6 +521,7 @@ impl ProjectPanel { - entry_id, - }); - -+ // FIXME add fuse dir specific behaviors - if let Some((worktree, entry)) = self.selected_sub_entry(cx) { - let auto_fold_dirs = ProjectPanelSettings::get_global(cx).auto_fold_dirs; - let is_root = Some(entry) == worktree.root_entry(); -diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs -index 005d086f48..1e5e9a6ac7 100644 ---- a/crates/zed/src/main.rs -+++ b/crates/zed/src/main.rs -@@ -523,10 +523,9 @@ fn main() { - Client::set_global(client.clone(), cx); - - zed::init(cx); -- mega::init(cx); - project::Project::init(&client, cx); - client::init(&client, cx); -- language::init(cx); -+ mega::init(cx); - let telemetry = client.telemetry(); - telemetry.start( - system_id.as_ref().map(|id| id.to_string()), --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0009-Fix-dont-restore-previous-workspace.patch b/scripts/zed-intergration/patches/0009-Fix-dont-restore-previous-workspace.patch deleted file mode 100644 index 4ded2c52a..000000000 --- a/scripts/zed-intergration/patches/0009-Fix-dont-restore-previous-workspace.patch +++ /dev/null @@ -1,254 +0,0 @@ -From 69f92bb2dbb1b2facf7b60cb6c6e1c0d211c4f4d Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 29 Oct 2024 21:08:56 +0800 -Subject: [PATCH 09/24] Fix: dont restore previous workspace - ---- - crates/project/src/project.rs | 106 ++++++++++++++++++++++ - crates/project_panel/src/project_panel.rs | 5 +- - crates/zed/src/main.rs | 85 +++++++++-------- - 3 files changed, 155 insertions(+), 41 deletions(-) - -diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs -index 6e731e9cba..6795d005d7 100644 ---- a/crates/project/src/project.rs -+++ b/crates/project/src/project.rs -@@ -576,6 +576,112 @@ impl Project { - TaskStore::init(Some(&client)); - } - -+ pub fn local_new ( -+ client: Arc, -+ node: NodeRuntime, -+ user_store: Model, -+ languages: Arc, -+ fs: Arc, -+ env: Option>, -+ cx: &mut AppContext, -+ ) -> Model { -+ cx.new_model(|cx: &mut ModelContext| { -+ let (tx, rx) = mpsc::unbounded(); -+ cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx)) -+ .detach(); -+ let snippets = SnippetProvider::new(fs.clone(), BTreeSet::from_iter([]), cx); -+ let worktree_store = cx.new_model(|_| WorktreeStore::local(false, fs.clone())); -+ cx.subscribe(&worktree_store, Self::on_worktree_store_event) -+ .detach(); -+ -+ let buffer_store = cx.new_model(|cx| BufferStore::local(worktree_store.clone(), cx)); -+ cx.subscribe(&buffer_store, Self::on_buffer_store_event) -+ .detach(); -+ -+ let prettier_store = cx.new_model(|cx| { -+ PrettierStore::new( -+ node.clone(), -+ fs.clone(), -+ languages.clone(), -+ worktree_store.clone(), -+ cx, -+ ) -+ }); -+ -+ let environment = ProjectEnvironment::new(&worktree_store, env, cx); -+ -+ let task_store = cx.new_model(|cx| { -+ TaskStore::local( -+ fs.clone(), -+ buffer_store.downgrade(), -+ worktree_store.clone(), -+ environment.clone(), -+ cx, -+ ) -+ }); -+ -+ let settings_observer = cx.new_model(|cx| { -+ SettingsObserver::new_local( -+ fs.clone(), -+ worktree_store.clone(), -+ task_store.clone(), -+ cx, -+ ) -+ }); -+ cx.subscribe(&settings_observer, Self::on_settings_observer_event) -+ .detach(); -+ -+ let lsp_store = cx.new_model(|cx| { -+ LspStore::new_local( -+ buffer_store.clone(), -+ worktree_store.clone(), -+ prettier_store.clone(), -+ environment.clone(), -+ languages.clone(), -+ client.http_client(), -+ fs.clone(), -+ cx, -+ ) -+ }); -+ cx.subscribe(&lsp_store, Self::on_lsp_store_event).detach(); -+ -+ Self { -+ buffer_ordered_messages_tx: tx, -+ collaborators: Default::default(), -+ worktree_store, -+ buffer_store, -+ lsp_store, -+ join_project_response_message_id: 0, -+ client_state: ProjectClientState::Local, -+ client_subscriptions: Vec::new(), -+ _subscriptions: vec![cx.on_release(Self::release)], -+ active_entry: None, -+ snippets, -+ languages, -+ client, -+ task_store, -+ user_store, -+ settings_observer, -+ fs, -+ ssh_client: None, -+ buffers_needing_diff: Default::default(), -+ git_diff_debouncer: DebouncedDelay::new(), -+ terminals: Terminals { -+ local_handles: Vec::new(), -+ }, -+ node: Some(node), -+ hosted_project_id: None, -+ dev_server_project_id: None, -+ search_history: Self::new_search_history(), -+ environment, -+ remotely_created_models: Default::default(), -+ -+ search_included_history: Self::new_search_history(), -+ search_excluded_history: Self::new_search_history(), -+ } -+ }) -+ } -+ - pub fn local( - client: Arc, - node: NodeRuntime, -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index 34f3bf0f54..8b16829834 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -286,6 +286,7 @@ impl ProjectPanel { - - cx.subscribe(&mega, |this, mega, mega_event, cx| match mega_event { - mega::Event::FuseMounted(Some(path)) => { -+ - let path = path.to_owned(); - this.workspace - .update(cx, |workspace, cx| { -@@ -302,8 +303,8 @@ impl ProjectPanel { - .detach() - }) - .log_err(); -- -- -+ -+ - } - mega::Event::FuseCheckout(path) => { - // FIXME: impl it. -diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs -index 1e5e9a6ac7..9df417f3e5 100644 ---- a/crates/zed/src/main.rs -+++ b/crates/zed/src/main.rs -@@ -867,49 +867,56 @@ async fn installation_id() -> Result { - Ok(IdType::New(installation_id)) - } - -+/// **Mega Fuse Integration:** -+/// -+/// This function is used for detect if there is an existing workspace opened -+/// in the last run. -+/// -+/// Whenever the case is, create an empty workspace -+/// because fuse dir cannot be warrantied to be available at zed startup. - async fn restore_or_create_workspace( - app_state: Arc, - cx: &mut AsyncAppContext, - ) -> Result<()> { -- if let Some(locations) = restorable_workspace_locations(cx, &app_state).await { -- for location in locations { -- match location { -- SerializedWorkspaceLocation::Local(location, _) => { -- let task = cx.update(|cx| { -- workspace::open_paths( -- location.paths().as_ref(), -- app_state.clone(), -- workspace::OpenOptions::default(), -- cx, -- ) -- })?; -- task.await?; -- } -- SerializedWorkspaceLocation::Ssh(ssh_project) => { -- let connection_options = SshConnectionOptions { -- host: ssh_project.host.clone(), -- username: ssh_project.user.clone(), -- port: ssh_project.port, -- password: None, -- }; -- let app_state = app_state.clone(); -- cx.spawn(move |mut cx| async move { -- recent_projects::open_ssh_project( -- connection_options, -- ssh_project.paths.into_iter().map(PathBuf::from).collect(), -- app_state, -- workspace::OpenOptions::default(), -- &mut cx, -- ) -- .await -- .log_err(); -- }) -- .detach(); -- } -- SerializedWorkspaceLocation::DevServer(_) => {} -- } -- } -- } else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) { -+ // if let Some(locations) = restorable_workspace_locations(cx, &app_state).await { -+ // for location in locations { -+ // match location { -+ // SerializedWorkspaceLocation::Local(location, _) => { -+ // let task = cx.update(|cx| { -+ // workspace::open_paths( -+ // location.paths().as_ref(), -+ // app_state.clone(), -+ // workspace::OpenOptions::default(), -+ // cx, -+ // ) -+ // })?; -+ // task.await?; -+ // } -+ // SerializedWorkspaceLocation::Ssh(ssh_project) => { -+ // let connection_options = SshConnectionOptions { -+ // host: ssh_project.host.clone(), -+ // username: ssh_project.user.clone(), -+ // port: ssh_project.port, -+ // password: None, -+ // }; -+ // let app_state = app_state.clone(); -+ // cx.spawn(move |mut cx| async move { -+ // recent_projects::open_ssh_project( -+ // connection_options, -+ // ssh_project.paths.into_iter().map(PathBuf::from).collect(), -+ // app_state, -+ // workspace::OpenOptions::default(), -+ // &mut cx, -+ // ) -+ // .await -+ // .log_err(); -+ // }) -+ // .detach(); -+ // } -+ // SerializedWorkspaceLocation::DevServer(_) => {} -+ // } -+ // } -+ if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) { - cx.update(|cx| show_welcome_view(app_state, cx))?.await?; - } else { - cx.update(|cx| { --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0010-Fix-checkout-in-project_panel.patch b/scripts/zed-intergration/patches/0010-Fix-checkout-in-project_panel.patch deleted file mode 100644 index 50aafd162..000000000 --- a/scripts/zed-intergration/patches/0010-Fix-checkout-in-project_panel.patch +++ /dev/null @@ -1,242 +0,0 @@ -From f2551513e804e8f43f6fac39d58befffd9dcda39 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Wed, 30 Oct 2024 10:53:59 +0800 -Subject: [PATCH 10/24] Fix checkout in project_panel - ---- - crates/mega/src/mega.rs | 18 +++++++++- - crates/mega_panel/src/mega_panel.rs | 28 +++++++-------- - crates/project_panel/src/project_panel.rs | 44 +++++++++++++++++------ - 3 files changed, 63 insertions(+), 27 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 84314de815..c27c40d7f4 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -123,7 +123,7 @@ impl Mega { - }).detach(); - } - -- pub fn checkout_path(&mut self, cx: &mut ModelContext) { -+ pub fn checkout_path(&mut self, cx: &mut ModelContext, mut path: PathBuf) { - // for now, we assume there's only one path being checkout at a time. - if self.checkout_path.is_none() { - cx.spawn(|_this, _cx| async { -@@ -137,6 +137,22 @@ impl Mega { - } - - -+ } -+ -+ pub fn checkout_multi_path(&mut self, cx: &mut ModelContext, mut path: Vec) { -+ // for now, we assume there's only one path being checkout at a time. -+ if self.checkout_path.is_none() { -+ cx.spawn(|_this, _cx| async { -+ let client = ReqwestClient::new(); -+ let req = client.get( -+ "localhost:2725/api/fs/mount", -+ AsyncBody::empty(), -+ false -+ ).await; -+ }).detach(); -+ } -+ -+ - } - - pub fn get_fuse_config(&self, cx: &mut ModelContext) { -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 82e6047244..8b141b57fd 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -5,7 +5,7 @@ use db::kvp::KEY_VALUE_STORE; - use fs::Fs; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; --use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement, PathPromptOptions, Pixels, PromptLevel, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext}; -+use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, EventEmitter, Flatten, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement, PathPromptOptions, Pixels, PromptLevel, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext}; - use mega::Mega; - use settings::Settings; - use std::sync::Arc; -@@ -257,6 +257,7 @@ impl MegaPanel { - // } - - self.mega_handle.update(cx, |this, cx | { -+ // FIXME when there's already a visible worktree, this call will create a new window. - this.toggle_mount(cx); - - }); -@@ -315,8 +316,6 @@ impl MegaPanel { - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -- -- - this.warn_unimplemented(cx); - })) - ), -@@ -326,7 +325,6 @@ impl MegaPanel { - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.warn_unimplemented(cx); -- // TODO: should read the path here - let options = PathPromptOptions { - files: true, - directories: true, -@@ -334,18 +332,18 @@ impl MegaPanel { - }; - - let abs_path = cx.prompt_for_paths(options); -- // if let Some(workspace_view) = this.workspace.upgrade() { -- // let mut workspace = workspace_view.read(cx); -- // workspace.open_workspace_for_paths(false, vec![], cx); -- // } -- cx.spawn(|this, mut cx| async move { -- let Ok(Ok(Some(result))) = abs_path.await else { -- return; -- }; -- -+ -+ // Why so annoying... -+ let mega = this.mega_handle.clone(); -+ cx.spawn(|this, mut cx|async move { -+ // mega.update(&mut cx, |this, cx| async move { -+ // if let Ok(Ok(Some(result))) = abs_path.await { -+ // this.checkout_multi_path(cx, result); -+ // } -+ // }).log_err(); - -- }).detach(); -- // mega.update(cx, |mega, cx| mega.checkout_path(cx)); -+ }) .detach(); -+ - })) - ), - ]) -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index 8b16829834..d69d682b8f 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -44,6 +44,7 @@ use std::{ - time::Duration, - }; - use db::write_and_log; -+use mega::Mega; - use theme::ThemeSettings; - use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem, Tooltip}; - use util::{maybe, ResultExt, TryFutureExt}; -@@ -58,7 +59,9 @@ const PROJECT_PANEL_KEY: &str = "ProjectPanel"; - const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX; - - pub struct ProjectPanel { -+ // TODO: use segment tree to fastly store multiple checkout path, - project: Model, -+ mega: Model, - fs: Arc, - scroll_handle: UniformListScrollHandle, - focus_handle: FocusHandle, -@@ -67,6 +70,7 @@ pub struct ProjectPanel { - /// Relevant only for auto-fold dirs, where a single project panel entry may actually consist of several - /// project entries (and all non-leaf nodes are guaranteed to be directories). - ancestors: HashMap, -+ checkout_entry_id: Option, - last_worktree_root_id: Option, - last_external_paths_drag_over_entry: Option, - expanded_dir_ids: HashMap>, -@@ -164,6 +168,7 @@ actions!( - UnfoldDirectory, - FoldDirectory, - SelectParent, -+ CheckoutPath, - ] - ); - -@@ -303,8 +308,8 @@ impl ProjectPanel { - .detach() - }) - .log_err(); -- -- -+ -+ this.focus_in(cx); - } - mega::Event::FuseCheckout(path) => { - // FIXME: impl it. -@@ -330,11 +335,13 @@ impl ProjectPanel { - - let mut this = Self { - project: project.clone(), -+ mega: mega.clone(), - fs: workspace.app_state().fs.clone(), - scroll_handle: UniformListScrollHandle::new(), - focus_handle, - visible_entries: Default::default(), - ancestors: Default::default(), -+ checkout_entry_id: Default::default(), - last_worktree_root_id: Default::default(), - last_external_paths_drag_over_entry: None, - expanded_dir_ids: Default::default(), -@@ -541,7 +548,10 @@ impl ProjectPanel { - menu.action("Search Inside", Box::new(NewSearchInDirectory)) - }) - } else { -- menu.action("New File", Box::new(NewFile)) -+ menu -+ .action("Checkout Path", Box::new(CheckoutPath)) -+ .separator() -+ .action("New File", Box::new(NewFile)) - .action("New Folder", Box::new(NewDirectory)) - .separator() - .when(is_local && cfg!(target_os = "macos"), |menu| { -@@ -1324,6 +1334,15 @@ impl ProjectPanel { - } - } - -+ fn checkout_specific_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { -+ if let Some((worktree, entry)) = self.selected_entry_handle(cx) { -+ let path = entry.path.clone(); -+ self.mega.update(cx, |this, cx| { -+ this.checkout_path(cx, path.to_path_buf()) -+ }); -+ } -+ } -+ - fn autoscroll(&mut self, cx: &mut ViewContext) { - if let Some((_, _, index)) = self.selection.and_then(|s| self.index_for_selection(s)) { - self.scroll_handle.scroll_to_item(index); -@@ -2937,6 +2956,7 @@ impl Render for ProjectPanel { - .on_action(cx.listener(Self::new_search_in_directory)) - .on_action(cx.listener(Self::unfold_directory)) - .on_action(cx.listener(Self::fold_directory)) -+ .on_action(cx.listener(Self::checkout_specific_path)) - .when(!project.is_read_only(cx), |el| { - el.on_action(cx.listener(Self::new_file)) - .on_action(cx.listener(Self::new_directory)) -@@ -3023,14 +3043,16 @@ impl Render for ProjectPanel { - .p_4() - .track_focus(&self.focus_handle) - .child( -- Button::new("open_project", "Open a project") -- .full_width() -- .key_binding(KeyBinding::for_action(&workspace::Open, cx)) -- .on_click(cx.listener(|this, _, cx| { -- this.workspace -- .update(cx, |workspace, cx| workspace.open(&workspace::Open, cx)) -- .log_err(); -- })), -+ // Button::new("open_project", "Open a project") -+ // .full_width() -+ // .key_binding(KeyBinding::for_action(&workspace::Open, cx)) -+ // .on_click(cx.listener(|this, _, cx| { -+ // this.workspace -+ // .update(cx, |workspace, cx| workspace.open(&workspace::Open, cx)) -+ // .log_err(); -+ // })), -+ Label::new("Run mega daemon to mount the working directories") -+ - ) - .drag_over::(|style, _, cx| { - style.bg(cx.theme().colors().drop_target_background) --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0011-Add-basic-mega-rest-api-support.patch b/scripts/zed-intergration/patches/0011-Add-basic-mega-rest-api-support.patch deleted file mode 100644 index 846112f5c..000000000 --- a/scripts/zed-intergration/patches/0011-Add-basic-mega-rest-api-support.patch +++ /dev/null @@ -1,835 +0,0 @@ -From a880b2c68d47990c8229656313b9dbeb1000b87c Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sun, 10 Nov 2024 22:19:15 +0800 -Subject: [PATCH 11/24] Add basic mega rest api support - ---- - Cargo.lock | 30 +++ - Cargo.toml | 1 + - crates/language/src/buffer.rs | 2 + - crates/mega/Cargo.toml | 5 +- - crates/mega/src/api.rs | 58 +++++ - crates/mega/src/delegate.rs | 58 ----- - crates/mega/src/fuse.rs | 0 - crates/mega/src/mega.rs | 354 +++++++++++++++++++--------- - crates/mega_panel/Cargo.toml | 5 +- - crates/mega_panel/src/mega_panel.rs | 45 +++- - crates/project/src/project.rs | 4 +- - crates/workspace/src/workspace.rs | 6 +- - 12 files changed, 387 insertions(+), 181 deletions(-) - create mode 100644 crates/mega/src/api.rs - delete mode 100644 crates/mega/src/delegate.rs - delete mode 100644 crates/mega/src/fuse.rs - -diff --git a/Cargo.lock b/Cargo.lock -index c25acea09d..a10bd2b986 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -4277,6 +4277,15 @@ dependencies = [ - "subtle", - ] - -+[[package]] -+name = "fid-rs" -+version = "0.2.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "a6956a1e60e2d1412b44b4169d44a03dae518f8583d3e10090c912c105e48447" -+dependencies = [ -+ "rayon", -+] -+ - [[package]] - name = "file_finder" - version = "0.1.0" -@@ -6635,6 +6644,15 @@ dependencies = [ - "imgref", - ] - -+[[package]] -+name = "louds-rs" -+version = "0.7.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "936de6c22f08e7135a921f8ada907acd0d88880c4f42b5591f634b9f1dd8e07f" -+dependencies = [ -+ "fid-rs", -+] -+ - [[package]] - name = "lru" - version = "0.12.4" -@@ -6890,11 +6908,14 @@ version = "0.1.0" - dependencies = [ - "anyhow", - "bytes 1.7.2", -+ "futures 0.3.30", - "gpui", - "reqwest_client", - "schemars", - "serde", -+ "serde_json", - "settings", -+ "trie-rs", - ] - - [[package]] -@@ -12517,6 +12538,15 @@ dependencies = [ - "tree-sitter-language", - ] - -+[[package]] -+name = "trie-rs" -+version = "0.4.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "f6f88f4b0a1ebd6c3d16be3e45eb0e8089372ccadd88849b7ca162ba64b5e6f6" -+dependencies = [ -+ "louds-rs", -+] -+ - [[package]] - name = "try-lock" - version = "0.2.5" -diff --git a/Cargo.toml b/Cargo.toml -index 6a02b98478..d459752aff 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -464,6 +464,7 @@ tree-sitter-ruby = "0.23" - tree-sitter-rust = "0.23" - tree-sitter-typescript = "0.23" - tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" } -+trie-rs = "0.4.2" - unicase = "2.6" - unindent = "0.1.7" - unicode-segmentation = "1.10" -diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs -index 28bbb25d1b..85f4f8cd10 100644 ---- a/crates/language/src/buffer.rs -+++ b/crates/language/src/buffer.rs -@@ -81,6 +81,8 @@ pub enum Capability { - ReadWrite, - /// The buffer is a read-only replica. - ReadOnly, -+ // /// The buffer is a mega-fuse replica. -+ // Fuse - } - - pub type BufferRow = u32; -diff --git a/crates/mega/Cargo.toml b/crates/mega/Cargo.toml -index 658ed87476..a767dfad66 100644 ---- a/crates/mega/Cargo.toml -+++ b/crates/mega/Cargo.toml -@@ -13,10 +13,13 @@ path = 'src/mega.rs' - - [dependencies] - gpui.workspace = true --reqwest_client.workspace = true - settings.workspace = true -+reqwest_client.workspace = true - -+futures.workspace = true - serde.workspace = true -+serde_json.workspace = true - bytes.workspace = true - schemars.workspace = true - anyhow.workspace = true -+trie-rs.workspace = true -diff --git a/crates/mega/src/api.rs b/crates/mega/src/api.rs -new file mode 100644 -index 0000000000..210d66884b ---- /dev/null -+++ b/crates/mega/src/api.rs -@@ -0,0 +1,58 @@ -+use serde::{Deserialize, Serialize}; -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct MountRequest { -+ pub path: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct MountResponse { -+ pub status: String, -+ pub mount: MountInfo, -+ pub message: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct MountInfo { -+ pub hash: String, -+ pub path: String, -+ pub inode: u64, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct MountsResponse { -+ pub status: String, -+ pub mounts: Vec, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct UmountRequest { -+ pub path: Option, -+ pub inode: Option, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct UmountResponse { -+ pub status: String, -+ pub message: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct ConfigResponse { -+ pub status: String, -+ pub config: ConfigInfo, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct ConfigInfo { -+ pub mega_url: String, -+ pub mount_path: String, -+ pub store_path: String, -+} -+ -+#[derive(Debug, Deserialize, Serialize)] -+pub struct ConfigRequest { -+ pub mega_url: Option, -+ pub mount_path: Option, -+ pub store_path: Option, -+} -\ No newline at end of file -diff --git a/crates/mega/src/delegate.rs b/crates/mega/src/delegate.rs -deleted file mode 100644 -index c767060048..0000000000 ---- a/crates/mega/src/delegate.rs -+++ /dev/null -@@ -1,58 +0,0 @@ --use serde::{Deserialize, Serialize}; -- --#[derive(Debug, Deserialize, Serialize)] --pub(crate) struct MountRequest { -- pub(crate) path: String, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct MountResponse { -- status: String, -- mount: MountInfo, -- message: String, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct MountInfo { -- hash: String, -- path: String, -- inode: u64, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct MountsResponse { -- status: String, -- mounts: Vec, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct UmountRequest { -- path: Option, -- inode: Option, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct UmountResponse { -- status: String, -- message: String, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct ConfigResponse { -- status: String, -- config: ConfigInfo, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct ConfigInfo { -- mega_url: String, -- mount_path: String, -- store_path: String, --} -- --#[derive(Debug, Deserialize, Serialize)] --struct ConfigRequest { -- mega_url: Option, -- mount_path: Option, -- store_path: Option, --} -\ No newline at end of file -diff --git a/crates/mega/src/fuse.rs b/crates/mega/src/fuse.rs -deleted file mode 100644 -index e69de29bb2..0000000000 -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index c27c40d7f4..d1d0c8e49b 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -1,24 +1,34 @@ - // This crate delegate mega and its fuse daemon. - // The following requirements should be met: --// -+// - // TODO: --// 1. Only one daemon on this machine. -+// 1. Only one daemon on this machine. - // This should be both warrantied by this module and scorpio - // 2. At least one daemon on this machine when zed startup. - // 3. Complete docs. - // 4. Add settings for this module - --use std::path::{Path, PathBuf}; --use std::sync::Arc; --use gpui::http_client::{AsyncBody, HttpClient}; --use gpui::{AppContext, Context, EntityId, EventEmitter, ModelContext, SharedString, WindowContext}; -+use crate::api::{ConfigRequest, ConfigResponse, MountResponse, MountsResponse}; -+use crate::mega_settings::MegaSettings; -+use futures::channel::oneshot; -+use futures::channel::oneshot::Receiver; -+use futures::{AsyncReadExt, FutureExt, SinkExt, TryFutureExt}; -+use gpui::http_client::{ -+ AsyncBody, HttpClient, HttpRequestExt -+ , -+}; -+use gpui::{ -+ AppContext, Context, EventEmitter, ModelContext, -+}; - use reqwest_client::ReqwestClient; -+use schemars::_private::NoSerialize; - use serde::Serialize; - use settings::Settings; --use crate::mega_settings::MegaSettings; -+use std::io::Read; -+use std::path::PathBuf; -+use std::sync::Arc; - --mod delegate; --mod fuse; -+mod api; - mod mega_settings; - - pub fn init(cx: &mut AppContext) { -@@ -27,158 +37,290 @@ pub fn init(cx: &mut AppContext) { - - #[derive(Clone, Debug, PartialEq)] - pub enum Event { -- MegaRunning(bool), - FuseRunning(bool), - FuseMounted(Option), - FuseCheckout(Option), - } - pub struct Mega { -- mega_running: bool, - fuse_running: bool, - fuse_mounted: bool, -- -+ - mount_point: Option, -- checkout_path: Option, -- -+ checkout_path: Vec, -+ - mega_url: String, - fuse_url: String, -+ http_client: Arc, - } - - pub struct MegaFuse {} - - impl EventEmitter for Mega {} - -- - impl Mega { -- pub fn init_settings(cx: &mut AppContext) { MegaSettings::register(cx); } -- -+ pub fn init_settings(cx: &mut AppContext) { -+ MegaSettings::register(cx); -+ } -+ - pub fn init(cx: &mut AppContext) { - Self::init_settings(cx); - } -- -+ - pub fn new(cx: &mut AppContext) -> Self { -- let mount_point = PathBuf::from(MegaSettings::get_global(cx).mount_point.clone()); -+ let mount_path = PathBuf::from(MegaSettings::get_global(cx).mount_point.clone()); - let mega_url = MegaSettings::get_global(cx).mega_url.clone(); - let fuse_url = MegaSettings::get_global(cx).fuse_url.clone(); -- -+ -+ // To not affected by global proxy settings. -+ let client = ReqwestClient::new(); -+ -+ let mount_point = if mount_path.exists() { -+ Some(mount_path) -+ } else { -+ None -+ }; -+ - Mega { - fuse_running: false, -- mega_running: false, - fuse_mounted: false, -- -- mount_point: None, -- checkout_path: None, -- -+ -+ mount_point, -+ checkout_path: Vec::new(), -+ - mega_url, - fuse_url, -+ http_client: Arc::new(client), - } - } - - pub fn update_status(&mut self, cx: &mut ModelContext) { -+ let recv = self.get_mount_point(cx); - -- -- -- cx.notify(); -- } -+ fn merge_trie(mut a: &Vec, b: &Vec ) { -+ todo!() -+ } - -- pub fn status(&self) -> (bool, bool, bool) { -- (self.mega_running, self.fuse_running, self.fuse_mounted) -+ cx.spawn(|this, mut cx| async move { -+ if let Ok(opt) = recv.await { -+ match opt { -+ None => { -+ // This means we cannot connect to a localhost port. -+ // So we can assume that fuse has been dead. -+ this.update(&mut cx, |mega, cx| { -+ mega.fuse_running = false; -+ cx.emit(Event::FuseRunning(false)); -+ cx.emit(Event::FuseMounted(None)); -+ }) -+ } -+ Some(info) => { -+ this.update(&mut cx, |mega, cx| { -+ // merge them -+ }) -+ } -+ } -+ } else { -+ Ok(()) -+ } -+ }) -+ .detach(); - } -- -- pub fn toggle_mega(&mut self, cx: &mut ModelContext) { -- self.mega_running = !self.mega_running; -- cx.emit(Event::MegaRunning(self.mega_running)); -+ -+ pub fn status(&self) -> (bool, bool) { -+ (self.fuse_running, self.fuse_mounted) - } -- -+ - pub fn toggle_fuse(&mut self, cx: &mut ModelContext) { -+ // FIXME should be able to restart fuse - self.fuse_running = !self.fuse_running; - cx.emit(Event::FuseRunning(self.fuse_running)); - } - - pub fn toggle_mount(&mut self, cx: &mut ModelContext) { -- // let req_body = delegate::MountRequest { -- // path: "".parse().unwrap() -- // }; -- -+ // TODO traverse checkout paths and toggle them -+ // persistently store them? -+ - cx.spawn(|this, mut cx| async move { -- let client = ReqwestClient::new(); -- let req = client.get( -- "localhost:2725/api/fs/mount", -- AsyncBody::empty(), -- false -- ).await; -- -- if let Some(mega) = this.upgrade() { -- let _ = mega.update(&mut cx, |this, cx| { -- if this.fuse_mounted { -- this.fuse_mounted = false; -- } else { -- // FIXME just pretending that we've got something from fuse response -- this.fuse_mounted = true; -- this.mount_point = Some(PathBuf::from("/home/neon/projects")); -- } -- cx.emit(Event::FuseMounted(this.mount_point.clone())); -- }); -- } -- }).detach(); -+ // let client = ReqwestClient::new(); -+ // let req = client.get( -+ // "localhost:2725/api/fs/mount", -+ // AsyncBody::empty(), -+ // false -+ // ).await; -+ // -+ // if let Some(mega) = this.upgrade() { -+ // let _ = mega.update(&mut cx, |this, cx| { -+ // if this.fuse_mounted { -+ // this.fuse_mounted = false; -+ // } else { -+ // // FIXME just pretending that we've got something from fuse response -+ // this.fuse_mounted = true; -+ // this.mount_point = Some(PathBuf::from("/home/neon/projects")); -+ // } -+ // cx.emit(Event::FuseMounted(this.mount_point.clone())); -+ // }); -+ // } -+ }) -+ .detach(); - } -- -- pub fn checkout_path(&mut self, cx: &mut ModelContext, mut path: PathBuf) { -- // for now, we assume there's only one path being checkout at a time. -- if self.checkout_path.is_none() { -- cx.spawn(|_this, _cx| async { -- let client = ReqwestClient::new(); -- let req = client.get( -- "localhost:2725/api/fs/mount", -+ -+ pub fn checkout_path(&mut self, cx: &mut ModelContext, mut path: PathBuf) -> Receiver> { -+ let (tx, rx) = oneshot::channel(); -+ let client = self.http_client.clone(); -+ let uri = format!( -+ // FIXME: settings not work, currently -+ "{base}/api/fs/mount", -+ base = self.fuse_url -+ ); -+ -+ cx.spawn(|_this, _cx| async move { -+ if let Ok(mut resp) = client -+ .get( -+ "http://127.0.0.1:2725/api/fs/mount", - AsyncBody::empty(), -- false -- ).await; -- }).detach(); -- } -- -- -+ false, -+ ) -+ .await -+ { -+ if resp.status().is_success() { -+ let mut buf = Vec::new(); -+ resp.body_mut().read_to_end(&mut buf).await.unwrap(); -+ if let Ok(config) = -+ serde_json::from_slice::(&*buf.into_boxed_slice()) -+ { -+ tx.send(Some(config)).unwrap(); -+ } -+ } -+ return; -+ } -+ -+ tx.send(None).unwrap(); -+ }) -+ .detach(); -+ -+ rx - } - - pub fn checkout_multi_path(&mut self, cx: &mut ModelContext, mut path: Vec) { -- // for now, we assume there's only one path being checkout at a time. -- if self.checkout_path.is_none() { -- cx.spawn(|_this, _cx| async { -- let client = ReqwestClient::new(); -- let req = client.get( -- "localhost:2725/api/fs/mount", -+ unimplemented!() -+ } -+ -+ pub fn get_mount_point(&mut self, cx: &mut ModelContext) -> Receiver> { -+ let (tx, rx) = oneshot::channel(); -+ let client = self.http_client.clone(); -+ let uri = format!( -+ // FIXME: settings not work, currently -+ "{base}/api/fs/mpoint", -+ base = self.fuse_url -+ ); -+ -+ cx.spawn(|_this, _cx| async move { -+ if let Ok(mut resp) = client -+ .get( -+ "http://127.0.0.1:2725/api/fs/mpoint", - AsyncBody::empty(), -- false -- ).await; -- }).detach(); -- } -+ false, -+ ) -+ .await -+ { -+ if resp.status().is_success() { -+ let mut buf = Vec::new(); -+ resp.body_mut().read_to_end(&mut buf).await.unwrap(); -+ if let Ok(config) = -+ serde_json::from_slice::(&*buf.into_boxed_slice()) -+ { -+ tx.send(Some(config)).unwrap(); -+ } -+ } -+ return; -+ } - -+ tx.send(None).unwrap(); -+ }) -+ .detach(); - -+ rx - } - -- pub fn get_fuse_config(&self, cx: &mut ModelContext) { -- cx.spawn(|_this, _cx| async { -- let client = ReqwestClient::new(); -- let req = client.get( -- "localhost:2725/api/fs/mount", -- AsyncBody::empty(), -- false -- ).await; -- }).detach(); -- } -+ pub fn get_fuse_config( -+ &mut self, -+ cx: &mut ModelContext, -+ ) -> Receiver> { -+ let (tx, rx) = oneshot::channel(); -+ let client = self.http_client.clone(); -+ let uri = format!( -+ // FIXME: settings not work, currently -+ "{base}/api/config", -+ base = self.fuse_url -+ ); -+ -+ cx.spawn(|_this, _cx| async move { -+ if let Ok(mut resp) = client -+ .get( -+ "http://127.0.0.1:2725/api/config", -+ AsyncBody::empty(), -+ false, -+ ) -+ .await -+ { -+ if resp.status().is_success() { -+ let mut buf = Vec::new(); -+ resp.body_mut().read_to_end(&mut buf).await.unwrap(); -+ if let Ok(config) = -+ serde_json::from_slice::(&*buf.into_boxed_slice()) -+ { -+ tx.send(Some(config)).unwrap(); -+ } -+ } -+ return; -+ } -+ -+ tx.send(None).unwrap(); -+ }) -+ .detach(); - -- pub fn set_fuse_config(&self, cx: &mut ModelContext) { -- cx.spawn(|_this, _cx| async { -- let client = ReqwestClient::new(); -- let req = client.post_json( -- "localhost:2725/api/config", -- AsyncBody::empty(), -- ).await; -- }).detach(); -+ rx - } -- --} - --#[cfg(test)] --mod test { -+ pub fn set_fuse_config(&self, cx: &mut ModelContext) -> Receiver> { -+ let (tx, rx) = oneshot::channel(); -+ let client = self.http_client.clone(); -+ let uri = format!( -+ // FIXME: settings not work, currently -+ "{base}/api/config", -+ base = self.fuse_url -+ ); -+ let config = ConfigRequest { -+ mega_url: None, -+ mount_path: None, -+ store_path: None, -+ }; -+ -+ let config = serde_json::to_string(&config).unwrap(); - -+ cx.spawn(|_this, _cx| async move { -+ if let Ok(mut resp) = client -+ .post_json( -+ "http://127.0.0.1:2725/api/config", -+ config.into() -+ ) -+ .await -+ { -+ if resp.status().is_success() { -+ let mut buf = Vec::new(); -+ resp.body_mut().read_to_end(&mut buf).await.unwrap(); -+ if let Ok(config) = -+ serde_json::from_slice::(&*buf.into_boxed_slice()) -+ { -+ tx.send(Some(config)).unwrap(); -+ } -+ } -+ return; -+ } -+ -+ tx.send(None).unwrap(); -+ }) -+ .detach(); -+ -+ rx -+ } - } -diff --git a/crates/mega_panel/Cargo.toml b/crates/mega_panel/Cargo.toml -index 2238a405c1..af520b2100 100644 ---- a/crates/mega_panel/Cargo.toml -+++ b/crates/mega_panel/Cargo.toml -@@ -11,10 +11,11 @@ path = 'src/mega_panel.rs' - workspace = true - - [dependencies] -+gpui = { workspace = true, features = ['test-support']} -+workspace = { workspace = true, features = ["test-support"]} -+ - mega.workspace = true --workspace.workspace = true - worktree.workspace = true --gpui.workspace = true - file_icons.workspace = true - settings.workspace = true - db.workspace = true -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 8b141b57fd..20b5160bab 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -265,7 +265,6 @@ impl MegaPanel { - - fn render_status(&mut self, cx: &mut ViewContext) -> Div { - let ( -- mega_running, - fuse_running, - fuse_mounted - ) = self.mega_handle.read(cx).status(); -@@ -273,7 +272,6 @@ impl MegaPanel { - v_flex() - .gap_1() - .children([ -- self.status_unit(cx, "Mega Backend:", mega_running), - self.status_unit(cx, "Scorpio Backend:", fuse_running), - self.status_unit(cx, "Fuse Mounted:", fuse_mounted), - ]) -@@ -292,15 +290,6 @@ impl MegaPanel { - .id("mega-control-pad") - .size_full() - .children([ -- encap_btn(Button::new("btn_toggle_mega", "Toggle Mega") -- .full_width() -- .icon(IconName::Plus) -- .icon_position(IconPosition::Start) -- .on_click(cx.listener(|this, _, cx| { -- this.mega_handle.update(cx, |mega, cx| mega.toggle_mega(cx)); -- this.warn_unimplemented(cx); -- })) -- ), - encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio") - .full_width() - .icon(IconName::Plus) -@@ -373,4 +362,36 @@ impl MegaPanel { - - fn horizontal_separator(cx: &mut WindowContext) -> Div { - div().mx_2().border_primary(cx).border_t_1() --} -\ No newline at end of file -+} -+ -+#[cfg(test)] -+mod tests { -+ use std::future::Future; -+ use db::smol::future::FutureExt; -+ use super::*; -+ use gpui::{TestAppContext, VisualTestContext}; -+ use workspace::AppState; -+ -+ #[gpui::test] -+ async fn test_mega_panel_functions(cx: &mut TestAppContext) { -+ let state = cx.update(|cx| { -+ let state = AppState::test(cx); -+ mega::init(cx); -+ state -+ }); -+ -+ state.mega.update(cx, |this, cx| { -+ let recv = this.get_fuse_config(cx); -+ cx.spawn(|_this, _cx| async move { -+ match recv.await.unwrap() { -+ None => panic!("Failed to get config"), -+ Some(config) => { -+ eprintln!("{config:?}"); -+ } -+ } -+ }).detach(); -+ }); -+ -+ } -+ -+} -diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs -index 6795d005d7..a103d677f9 100644 ---- a/crates/project/src/project.rs -+++ b/crates/project/src/project.rs -@@ -1874,7 +1874,9 @@ impl Project { - } - - pub fn is_read_only(&self, cx: &AppContext) -> bool { -- self.is_disconnected(cx) || self.capability() == Capability::ReadOnly -+ self.is_disconnected(cx) -+ || self.capability() == Capability::ReadOnly -+ // || self.capability() == Capability::Fuse - } - - pub fn is_local(&self) -> bool { -diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs -index af4f47e5d3..45d2aee826 100644 ---- a/crates/workspace/src/workspace.rs -+++ b/crates/workspace/src/workspace.rs -@@ -611,11 +611,15 @@ impl AppState { - let session = cx.new_model(|cx| AppSession::new(Session::test(), cx)); - let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx)); - let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx)); -- let mega = cx.new_model(|cx| { Mega::new(cx) }); - - theme::init(theme::LoadThemes::JustBase, cx); - client::init(&client, cx); - crate::init_settings(cx); -+ mega::init(cx); -+ -+ // We read settings in Mega::new() -+ // so the construction should be delayed. -+ let mega = cx.new_model(|cx| { Mega::new(cx) }); - - Arc::new(Self { - client, --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0012-fix-api-call-logic.patch b/scripts/zed-intergration/patches/0012-fix-api-call-logic.patch deleted file mode 100644 index 7c8be3b75..000000000 --- a/scripts/zed-intergration/patches/0012-fix-api-call-logic.patch +++ /dev/null @@ -1,611 +0,0 @@ -From 3c45fed1fd917dac0051917d7d9685371f35cd60 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 12 Nov 2024 16:56:00 +0800 -Subject: [PATCH 12/24] fix api call logic - ---- - Cargo.lock | 54 +++--- - Cargo.toml | 2 +- - crates/mega/Cargo.toml | 2 +- - crates/mega/src/api.rs | 8 +- - crates/mega/src/mega.rs | 209 ++++++++++++++++++---- - crates/mega_panel/src/mega_panel.rs | 73 ++++---- - crates/project_panel/src/project_panel.rs | 3 +- - 7 files changed, 241 insertions(+), 110 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index a10bd2b986..0483c524c4 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -3830,6 +3830,12 @@ version = "1.1.0" - source = "registry+https://github.com/rust-lang/crates.io-index" - checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" - -+[[package]] -+name = "endian-type" -+version = "0.1.2" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" -+ - [[package]] - name = "enum-ordinalize" - version = "4.3.0" -@@ -4277,15 +4283,6 @@ dependencies = [ - "subtle", - ] - --[[package]] --name = "fid-rs" --version = "0.2.0" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "a6956a1e60e2d1412b44b4169d44a03dae518f8583d3e10090c912c105e48447" --dependencies = [ -- "rayon", --] -- - [[package]] - name = "file_finder" - version = "0.1.0" -@@ -6644,15 +6641,6 @@ dependencies = [ - "imgref", - ] - --[[package]] --name = "louds-rs" --version = "0.7.0" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "936de6c22f08e7135a921f8ada907acd0d88880c4f42b5591f634b9f1dd8e07f" --dependencies = [ -- "fid-rs", --] -- - [[package]] - name = "lru" - version = "0.12.4" -@@ -6910,12 +6898,12 @@ dependencies = [ - "bytes 1.7.2", - "futures 0.3.30", - "gpui", -+ "radix_trie", - "reqwest_client", - "schemars", - "serde", - "serde_json", - "settings", -- "trie-rs", - ] - - [[package]] -@@ -7205,6 +7193,15 @@ version = "1.0.6" - source = "registry+https://github.com/rust-lang/crates.io-index" - checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -+[[package]] -+name = "nibble_vec" -+version = "0.1.0" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -+dependencies = [ -+ "smallvec", -+] -+ - [[package]] - name = "nix" - version = "0.29.0" -@@ -8840,6 +8837,16 @@ version = "0.7.0" - source = "registry+https://github.com/rust-lang/crates.io-index" - checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -+[[package]] -+name = "radix_trie" -+version = "0.2.1" -+source = "registry+https://github.com/rust-lang/crates.io-index" -+checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -+dependencies = [ -+ "endian-type", -+ "nibble_vec", -+] -+ - [[package]] - name = "rand" - version = "0.7.3" -@@ -12538,15 +12545,6 @@ dependencies = [ - "tree-sitter-language", - ] - --[[package]] --name = "trie-rs" --version = "0.4.2" --source = "registry+https://github.com/rust-lang/crates.io-index" --checksum = "f6f88f4b0a1ebd6c3d16be3e45eb0e8089372ccadd88849b7ca162ba64b5e6f6" --dependencies = [ -- "louds-rs", --] -- - [[package]] - name = "try-lock" - version = "0.2.5" -diff --git a/Cargo.toml b/Cargo.toml -index d459752aff..4620119597 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -464,7 +464,7 @@ tree-sitter-ruby = "0.23" - tree-sitter-rust = "0.23" - tree-sitter-typescript = "0.23" - tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" } --trie-rs = "0.4.2" -+radix_trie = "0.2" - unicase = "2.6" - unindent = "0.1.7" - unicode-segmentation = "1.10" -diff --git a/crates/mega/Cargo.toml b/crates/mega/Cargo.toml -index a767dfad66..a9a4f9d9b7 100644 ---- a/crates/mega/Cargo.toml -+++ b/crates/mega/Cargo.toml -@@ -22,4 +22,4 @@ serde_json.workspace = true - bytes.workspace = true - schemars.workspace = true - anyhow.workspace = true --trie-rs.workspace = true -+radix_trie.workspace = true -diff --git a/crates/mega/src/api.rs b/crates/mega/src/api.rs -index 210d66884b..efbf0d1752 100644 ---- a/crates/mega/src/api.rs -+++ b/crates/mega/src/api.rs -@@ -1,8 +1,8 @@ - use serde::{Deserialize, Serialize}; - - #[derive(Debug, Deserialize, Serialize)] --pub struct MountRequest { -- pub path: String, -+pub struct MountRequest<'a> { -+ pub path: &'a str, - } - - #[derive(Debug, Deserialize, Serialize)] -@@ -26,8 +26,8 @@ pub struct MountsResponse { - } - - #[derive(Debug, Deserialize, Serialize)] --pub struct UmountRequest { -- pub path: Option, -+pub struct UmountRequest<'a> { -+ pub path: Option<&'a str>, - pub inode: Option, - } - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index d1d0c8e49b..f76a139148 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -8,25 +8,28 @@ - // 3. Complete docs. - // 4. Add settings for this module - --use crate::api::{ConfigRequest, ConfigResponse, MountResponse, MountsResponse}; -+use crate::api::{ -+ ConfigRequest, ConfigResponse, MountRequest, MountResponse, MountsResponse, UmountRequest, -+ UmountResponse, -+}; - use crate::mega_settings::MegaSettings; -+use crate::Event::FuseMounted; - use futures::channel::oneshot; - use futures::channel::oneshot::Receiver; - use futures::{AsyncReadExt, FutureExt, SinkExt, TryFutureExt}; --use gpui::http_client::{ -- AsyncBody, HttpClient, HttpRequestExt -- , --}; --use gpui::{ -- AppContext, Context, EventEmitter, ModelContext, --}; -+use gpui::http_client::{AsyncBody, HttpClient, HttpRequestExt}; -+use gpui::{AppContext, Context, EventEmitter, ModelContext, Path}; -+use radix_trie::{Trie, TrieCommon}; - use reqwest_client::ReqwestClient; - use schemars::_private::NoSerialize; - use serde::Serialize; - use settings::Settings; -+use std::collections::{BTreeMap, BTreeSet, HashSet}; -+use std::ffi::OsStr; -+use std::hash::{DefaultHasher, Hash, Hasher}; - use std::io::Read; - use std::path::PathBuf; --use std::sync::Arc; -+use std::sync::{Arc, RwLock}; - - mod api; - mod mega_settings; -@@ -41,12 +44,17 @@ pub enum Event { - FuseMounted(Option), - FuseCheckout(Option), - } -+ -+struct CheckoutState { -+ path: PathBuf, -+ mounted: bool, -+} - pub struct Mega { - fuse_running: bool, - fuse_mounted: bool, - - mount_point: Option, -- checkout_path: Vec, -+ checkout_path: Trie, - - mega_url: String, - fuse_url: String, -@@ -85,7 +93,7 @@ impl Mega { - fuse_mounted: false, - - mount_point, -- checkout_path: Vec::new(), -+ checkout_path: Default::default(), - - mega_url, - fuse_url, -@@ -94,14 +102,11 @@ impl Mega { - } - - pub fn update_status(&mut self, cx: &mut ModelContext) { -- let recv = self.get_mount_point(cx); -- -- fn merge_trie(mut a: &Vec, b: &Vec ) { -- todo!() -- } -+ let checkouts = self.get_checkout_paths(cx); -+ let config = self.get_fuse_config(cx); - - cx.spawn(|this, mut cx| async move { -- if let Ok(opt) = recv.await { -+ if let Ok(opt) = checkouts.await { - match opt { - None => { - // This means we cannot connect to a localhost port. -@@ -113,14 +118,37 @@ impl Mega { - }) - } - Some(info) => { -+ // Check if checkout-ed paths are correct - this.update(&mut cx, |mega, cx| { -- // merge them -+ let trie = &mut mega.checkout_path; -+ for ref i in info.mounts { -+ let missing = trie.get_ancestor(&i.path).is_none(); -+ if missing { -+ // Should not happen unless on startup. -+ trie.insert(i.path.clone(), i.inode); -+ cx.emit(Event::FuseCheckout(Some(PathBuf::from(i.path.clone())))) -+ } -+ } - }) - } - } -- } else { -- Ok(()) -- } -+ } else { Ok(()) }.unwrap(); -+ -+ // When mount point changed, emit an event. -+ if let Ok(Some(config)) = config.await { -+ this.update(&mut cx, |this, cx| { -+ let path = PathBuf::from(config.config.mount_path); -+ if (this.fuse_mounted && this.fuse_running) -+ && this.mount_point.is_some() { -+ if let Some(inner) = &this.mount_point { -+ if !inner.eq(&path) { -+ this.mount_point = Some(path); -+ cx.emit(Event::FuseMounted(this.mount_point.clone())); -+ } -+ } -+ } -+ }) -+ } else { Ok(()) } - }) - .detach(); - } -@@ -136,9 +164,58 @@ impl Mega { - } - - pub fn toggle_mount(&mut self, cx: &mut ModelContext) { -- // TODO traverse checkout paths and toggle them -- // persistently store them? -- -+ // TODO traverse checkout-ed paths and toggle them -+ self.update_status(cx); -+ let paths = &self.checkout_path; -+ -+ if !self.fuse_mounted { -+ for (_, (p, _)) in paths.iter().enumerate() { -+ let path = PathBuf::from(p); // FIXME is there a better way? -+ cx.spawn(|mega, mut cx| async move { -+ let recv = mega.update(&mut cx, |this, cx| { -+ let param = PathBuf::from(path); -+ this.checkout_path(cx, param) -+ }).expect("mega delegate not be dropped"); -+ -+ if let Ok(Some(resp)) = recv.await { -+ mega.update(&mut cx, |this, cx| { -+ let buf = PathBuf::from(resp.mount.path.clone()); -+ cx.emit(Event::FuseCheckout(Some(buf))); -+ }) -+ } else { -+ Ok(()) -+ } -+ }) -+ .detach(); -+ } -+ -+ self.fuse_mounted = true; -+ cx.emit(Event::FuseMounted(self.mount_point.clone())); -+ } else { -+ for (_, (p, &n)) in paths.iter().enumerate() { -+ let path = PathBuf::from(p); // FIXME is there a better way? -+ cx.spawn(|mega, mut cx| async move { -+ let recv = mega.update(&mut cx, |this, cx| { -+ let param = PathBuf::from(path); -+ this.restore_path(cx, param, n) -+ }).expect("mega delegate not be dropped"); -+ -+ if let Ok(Some(resp)) = recv.await { -+ mega.update(&mut cx, |this, cx| { -+ // TODO use a new check out state struct -+ cx.emit(Event::FuseCheckout(None)); -+ }) -+ } else { -+ Ok(()) -+ } -+ }) -+ .detach(); -+ } -+ -+ self.fuse_mounted = false; -+ cx.emit(Event::FuseMounted(None)); -+ } -+ - cx.spawn(|this, mut cx| async move { - // let client = ReqwestClient::new(); - // let req = client.get( -@@ -163,7 +240,11 @@ impl Mega { - .detach(); - } - -- pub fn checkout_path(&mut self, cx: &mut ModelContext, mut path: PathBuf) -> Receiver> { -+ pub fn checkout_path( -+ &self, -+ cx: &ModelContext, -+ path: PathBuf, -+ ) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -@@ -172,11 +253,16 @@ impl Mega { - base = self.fuse_url - ); - -+ // If it panics, that means there's a bug in code. -+ let path = path.to_str().unwrap(); -+ let req = MountRequest { path }; -+ let body = serde_json::to_string(&req).unwrap(); -+ - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client - .get( - "http://127.0.0.1:2725/api/fs/mount", -- AsyncBody::empty(), -+ AsyncBody::from(body), - false, - ) - .await -@@ -195,7 +281,7 @@ impl Mega { - - tx.send(None).unwrap(); - }) -- .detach(); -+ .detach(); - - rx - } -@@ -204,7 +290,57 @@ impl Mega { - unimplemented!() - } - -- pub fn get_mount_point(&mut self, cx: &mut ModelContext) -> Receiver> { -+ pub fn restore_path( -+ &self, -+ cx: &ModelContext, -+ path: PathBuf, -+ inode: u64, -+ ) -> Receiver> { -+ let (tx, rx) = oneshot::channel(); -+ let client = self.http_client.clone(); -+ let uri = format!( -+ // FIXME: settings not work, currently -+ "{base}/api/fs/umount", -+ base = self.fuse_url -+ ); -+ -+ // If it panics, that means there's a bug in code. -+ let path = path.to_str().unwrap(); -+ let req = UmountRequest { -+ path: Some(path), -+ inode: Some(inode), -+ }; -+ let body = serde_json::to_string(&req).unwrap(); -+ -+ cx.spawn(|_this, _cx| async move { -+ if let Ok(mut resp) = client -+ .get( -+ "http://127.0.0.1:2725/api/fs/umount", -+ AsyncBody::from(body), -+ false, -+ ) -+ .await -+ { -+ if resp.status().is_success() { -+ let mut buf = Vec::new(); -+ resp.body_mut().read_to_end(&mut buf).await.unwrap(); -+ if let Ok(config) = -+ serde_json::from_slice::(&*buf.into_boxed_slice()) -+ { -+ tx.send(Some(config)).unwrap(); -+ } -+ } -+ return; -+ } -+ -+ tx.send(None).unwrap(); -+ }) -+ .detach(); -+ -+ rx -+ } -+ -+ pub fn get_checkout_paths(&self, cx: &ModelContext) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -@@ -241,10 +377,7 @@ impl Mega { - rx - } - -- pub fn get_fuse_config( -- &mut self, -- cx: &mut ModelContext, -- ) -> Receiver> { -+ pub fn get_fuse_config(&self, cx: &ModelContext) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -@@ -299,10 +432,7 @@ impl Mega { - - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client -- .post_json( -- "http://127.0.0.1:2725/api/config", -- config.into() -- ) -+ .post_json("http://127.0.0.1:2725/api/config", config.into()) - .await - { - if resp.status().is_success() { -@@ -319,8 +449,13 @@ impl Mega { - - tx.send(None).unwrap(); - }) -- .detach(); -+ .detach(); - - rx - } -+ -+ pub fn is_path_checkout(&self, path: &String) -> bool { -+ let set = &self.checkout_path; -+ set.get_ancestor(path).is_some() -+ } - } -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 20b5160bab..fe55670a44 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -294,47 +294,46 @@ impl MegaPanel { - .full_width() - .icon(IconName::Plus) - .icon_position(IconPosition::Start) -- .on_click(cx.listener(|this, _, cx| { -- this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); -- this.warn_unimplemented(cx); -- })) -- ), -- encap_btn(Button::new("btn_toggle_mount", "Toggle Mount") -- .full_width() -- .icon(IconName::Context) -- .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -- this.warn_unimplemented(cx); -- })) -- ), -- encap_btn(Button::new("btn_checkout", "Checkout Path") -- .full_width() -- .icon(IconName::Check) -- .icon_position(IconPosition::Start) -- .on_click(cx.listener(|this, _, cx| { -- this.warn_unimplemented(cx); -- let options = PathPromptOptions { -- files: true, -- directories: true, -- multiple: false, -- }; -- -- let abs_path = cx.prompt_for_paths(options); -- -- // Why so annoying... -- let mega = this.mega_handle.clone(); -- cx.spawn(|this, mut cx|async move { -- // mega.update(&mut cx, |this, cx| async move { -- // if let Ok(Ok(Some(result))) = abs_path.await { -- // this.checkout_multi_path(cx, result); -- // } -- // }).log_err(); -- -- }) .detach(); -- - })) - ), -+ // encap_btn(Button::new("btn_toggle_mount", "Toggle Mount") -+ // .full_width() -+ // .icon(IconName::Context) -+ // .icon_position(IconPosition::Start) -+ // .on_click(cx.listener(|this, _, cx| { -+ // this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -+ // this.warn_unimplemented(cx); -+ // })) -+ // ), -+ // encap_btn(Button::new("btn_checkout", "Checkout Path") -+ // .full_width() -+ // .icon(IconName::Check) -+ // .icon_position(IconPosition::Start) -+ // .on_click(cx.listener(|this, _, cx| { -+ // this.warn_unimplemented(cx); -+ // let options = PathPromptOptions { -+ // files: true, -+ // directories: true, -+ // multiple: false, -+ // }; -+ // -+ // let abs_path = cx.prompt_for_paths(options); -+ // -+ // // Why so annoying... -+ // let mega = this.mega_handle.clone(); -+ // cx.spawn(|this, mut cx|async move { -+ // // mega.update(&mut cx, |this, cx| async move { -+ // // if let Ok(Ok(Some(result))) = abs_path.await { -+ // // this.checkout_multi_path(cx, result); -+ // // } -+ // // }).log_err(); -+ // -+ // }) .detach(); -+ // -+ // })) -+ // ), - ]) - } - -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index d69d682b8f..b2d4cda751 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -312,8 +312,7 @@ impl ProjectPanel { - this.focus_in(cx); - } - mega::Event::FuseCheckout(path) => { -- // FIXME: impl it. -- println!("Fuse Checkout NOT implemented in project for now!"); -+ // It's not important, for now. - } - _ => {} - }).detach(); --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0013-fix-features-wrongly-opened.patch b/scripts/zed-intergration/patches/0013-fix-features-wrongly-opened.patch deleted file mode 100644 index 53aac48b7..000000000 --- a/scripts/zed-intergration/patches/0013-fix-features-wrongly-opened.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 42916a9fae734c3a0b3dcc8d90f77669378a20c2 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 12 Nov 2024 17:55:27 +0800 -Subject: [PATCH 13/24] fix features wrongly opened - ---- - crates/mega_panel/Cargo.toml | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/crates/mega_panel/Cargo.toml b/crates/mega_panel/Cargo.toml -index af520b2100..d959d761a4 100644 ---- a/crates/mega_panel/Cargo.toml -+++ b/crates/mega_panel/Cargo.toml -@@ -11,8 +11,8 @@ path = 'src/mega_panel.rs' - workspace = true - - [dependencies] --gpui = { workspace = true, features = ['test-support']} --workspace = { workspace = true, features = ["test-support"]} -+gpui.workspace = true -+workspace.workspace = true - - mega.workspace = true - worktree.workspace = true -@@ -26,3 +26,7 @@ util.workspace = true - anyhow.workspace = true - serde.workspace = true - schemars.workspace = true -+ -+[dev-dependencies] -+gpui = { workspace = true, features = ['test-support']} -+workspace = { workspace = true, features = ["test-support"]} --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0014-fix-checkout-in-context-menu.patch b/scripts/zed-intergration/patches/0014-fix-checkout-in-context-menu.patch deleted file mode 100644 index f575ec002..000000000 --- a/scripts/zed-intergration/patches/0014-fix-checkout-in-context-menu.patch +++ /dev/null @@ -1,207 +0,0 @@ -From 14806e63bfc717cd17f933fb1aecd6cded410497 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 12 Nov 2024 19:12:29 +0800 -Subject: [PATCH 14/24] fix checkout in context menu - ---- - crates/mega/src/mega.rs | 47 ++++++----------------- - crates/mega_panel/src/mega_panel.rs | 15 ++------ - crates/project_panel/src/project_panel.rs | 15 ++++++-- - 3 files changed, 26 insertions(+), 51 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index f76a139148..41f89a7c1d 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -120,6 +120,8 @@ impl Mega { - Some(info) => { - // Check if checkout-ed paths are correct - this.update(&mut cx, |mega, cx| { -+ mega.fuse_running = true; -+ - let trie = &mut mega.checkout_path; - for ref i in info.mounts { - let missing = trie.get_ancestor(&i.path).is_none(); -@@ -158,13 +160,6 @@ impl Mega { - } - - pub fn toggle_fuse(&mut self, cx: &mut ModelContext) { -- // FIXME should be able to restart fuse -- self.fuse_running = !self.fuse_running; -- cx.emit(Event::FuseRunning(self.fuse_running)); -- } -- -- pub fn toggle_mount(&mut self, cx: &mut ModelContext) { -- // TODO traverse checkout-ed paths and toggle them - self.update_status(cx); - let paths = &self.checkout_path; - -@@ -186,11 +181,12 @@ impl Mega { - Ok(()) - } - }) -- .detach(); -+ .detach(); - } - - self.fuse_mounted = true; -- cx.emit(Event::FuseMounted(self.mount_point.clone())); -+ // FIXME: A configurable path from fuse api is needed. -+ cx.emit(Event::FuseMounted(Some(PathBuf::from("/home/neon/dic")))); - } else { - for (_, (p, &n)) in paths.iter().enumerate() { - let path = PathBuf::from(p); // FIXME is there a better way? -@@ -215,29 +211,12 @@ impl Mega { - self.fuse_mounted = false; - cx.emit(Event::FuseMounted(None)); - } -+ } - -- cx.spawn(|this, mut cx| async move { -- // let client = ReqwestClient::new(); -- // let req = client.get( -- // "localhost:2725/api/fs/mount", -- // AsyncBody::empty(), -- // false -- // ).await; -- // -- // if let Some(mega) = this.upgrade() { -- // let _ = mega.update(&mut cx, |this, cx| { -- // if this.fuse_mounted { -- // this.fuse_mounted = false; -- // } else { -- // // FIXME just pretending that we've got something from fuse response -- // this.fuse_mounted = true; -- // this.mount_point = Some(PathBuf::from("/home/neon/projects")); -- // } -- // cx.emit(Event::FuseMounted(this.mount_point.clone())); -- // }); -- // } -- }) -- .detach(); -+ pub fn toggle_mount(&mut self, cx: &mut ModelContext) { -+ // FIXME should be able to restart fuse -+ self.fuse_running = !self.fuse_running; -+ cx.emit(Event::FuseRunning(self.fuse_running)); - } - - pub fn checkout_path( -@@ -260,10 +239,9 @@ impl Mega { - - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client -- .get( -+ .post_json( - "http://127.0.0.1:2725/api/fs/mount", - AsyncBody::from(body), -- false, - ) - .await - { -@@ -314,10 +292,9 @@ impl Mega { - - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client -- .get( -+ .post_json( - "http://127.0.0.1:2725/api/fs/umount", - AsyncBody::from(body), -- false, - ) - .await - { -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index fe55670a44..5dec15a182 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -250,16 +250,8 @@ impl MegaPanel { - } - - pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { -- // if let Some(workspace) = self.workspace.upgrade() { -- // workspace.model.update(cx, |this, mx| { -- // -- // }); -- // } -- -- self.mega_handle.update(cx, |this, cx | { -- // FIXME when there's already a visible worktree, this call will create a new window. -+ self.mega_handle.update(cx, |this, cx | { - this.toggle_mount(cx); -- - }); - } - -@@ -278,7 +270,6 @@ impl MegaPanel { - } - - fn render_buttons(&mut self, cx: &mut ViewContext) -> impl IntoElement { -- - fn encap_btn(btn: Button) -> Div { - div() - .m_1() -@@ -290,12 +281,12 @@ impl MegaPanel { - .id("mega-control-pad") - .size_full() - .children([ -- encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio") -+ encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio Checkouts") - .full_width() - .icon(IconName::Plus) - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { -- this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -+ this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); - })) - ), - // encap_btn(Button::new("btn_toggle_mount", "Toggle Mount") -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index b2d4cda751..a83346ae60 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -291,7 +291,7 @@ impl ProjectPanel { - - cx.subscribe(&mega, |this, mega, mega_event, cx| match mega_event { - mega::Event::FuseMounted(Some(path)) => { -- -+ println!("Fuse Mounted: {path:?}"); - let path = path.to_owned(); - this.workspace - .update(cx, |workspace, cx| { -@@ -310,6 +310,9 @@ impl ProjectPanel { - .log_err(); - - this.focus_in(cx); -+ }, -+ mega::Event::FuseMounted(None) => { -+ // TODO: close the workspace - } - mega::Event::FuseCheckout(path) => { - // It's not important, for now. -@@ -1336,8 +1339,12 @@ impl ProjectPanel { - fn checkout_specific_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { - if let Some((worktree, entry)) = self.selected_entry_handle(cx) { - let path = entry.path.clone(); -- self.mega.update(cx, |this, cx| { -- this.checkout_path(cx, path.to_path_buf()) -+ self.mega.update(cx, |mega, cx| { -+ let recv = mega.checkout_path(cx, path.to_path_buf()); -+ cx.spawn(|_, _| async move { -+ let resp = recv.await; -+ println!("Response: {resp:?}"); -+ }).detach(); - }); - } - } -@@ -2363,7 +2370,7 @@ impl ProjectPanel { - .selection - .map_or(false, |selection| selection.entry_id == entry_id); - let width = self.size(cx); -- let filename_text_color = -+ let filename_text_color = - entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked); - let file_name = details.filename.clone(); - let mut icon = details.icon.clone(); --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0015-fix-reading-mega-settings.patch b/scripts/zed-intergration/patches/0015-fix-reading-mega-settings.patch deleted file mode 100644 index a703f85ba..000000000 --- a/scripts/zed-intergration/patches/0015-fix-reading-mega-settings.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 1f25b260f410733580a628a4d116a4d4cfbbc286 Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sun, 17 Nov 2024 11:59:31 +0800 -Subject: [PATCH 15/24] fix reading mega settings - ---- - crates/mega/src/mega.rs | 46 +++++++++++++++++++++----------- - crates/mega/src/mega_settings.rs | 10 +++---- - 2 files changed, 36 insertions(+), 20 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 41f89a7c1d..b33c487662 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -26,9 +26,11 @@ use serde::Serialize; - use settings::Settings; - use std::collections::{BTreeMap, BTreeSet, HashSet}; - use std::ffi::OsStr; -+use std::fmt::{Debug, Formatter}; - use std::hash::{DefaultHasher, Hash, Hasher}; - use std::io::Read; - use std::path::PathBuf; -+use std::process::Command; - use std::sync::{Arc, RwLock}; - - mod api; -@@ -49,7 +51,10 @@ struct CheckoutState { - path: PathBuf, - mounted: bool, - } -+ - pub struct Mega { -+ fuse_executable: PathBuf, -+ - fuse_running: bool, - fuse_mounted: bool, - -@@ -65,6 +70,17 @@ pub struct MegaFuse {} - - impl EventEmitter for Mega {} - -+impl Debug for Mega { -+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { -+ write!(f, -+ "fuse_executable: {:?}, mega_url: {}, fuse_url: {}", -+ self.fuse_executable, -+ self.mega_url, -+ self.fuse_url -+ ) -+ } -+} -+ - impl Mega { - pub fn init_settings(cx: &mut AppContext) { - MegaSettings::register(cx); -@@ -75,9 +91,10 @@ impl Mega { - } - - pub fn new(cx: &mut AppContext) -> Self { -- let mount_path = PathBuf::from(MegaSettings::get_global(cx).mount_point.clone()); -+ let mount_path = MegaSettings::get_global(cx).mount_point.clone(); - let mega_url = MegaSettings::get_global(cx).mega_url.clone(); - let fuse_url = MegaSettings::get_global(cx).fuse_url.clone(); -+ let fuse_executable = MegaSettings::get_global(cx).fuse_executable.clone(); - - // To not affected by global proxy settings. - let client = ReqwestClient::new(); -@@ -88,7 +105,9 @@ impl Mega { - None - }; - -- Mega { -+ let mega = Mega { -+ fuse_executable, -+ - fuse_running: false, - fuse_mounted: false, - -@@ -98,7 +117,10 @@ impl Mega { - mega_url, - fuse_url, - http_client: Arc::new(client), -- } -+ }; -+ println!("Mega New: {mega:?}"); -+ -+ mega - } - - pub fn update_status(&mut self, cx: &mut ModelContext) { -@@ -168,8 +190,7 @@ impl Mega { - let path = PathBuf::from(p); // FIXME is there a better way? - cx.spawn(|mega, mut cx| async move { - let recv = mega.update(&mut cx, |this, cx| { -- let param = PathBuf::from(path); -- this.checkout_path(cx, param) -+ this.checkout_path(cx, path) - }).expect("mega delegate not be dropped"); - - if let Ok(Some(resp)) = recv.await { -@@ -227,7 +248,6 @@ impl Mega { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -- // FIXME: settings not work, currently - "{base}/api/fs/mount", - base = self.fuse_url - ); -@@ -240,7 +260,7 @@ impl Mega { - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client - .post_json( -- "http://127.0.0.1:2725/api/fs/mount", -+ uri.as_str(), - AsyncBody::from(body), - ) - .await -@@ -277,7 +297,6 @@ impl Mega { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -- // FIXME: settings not work, currently - "{base}/api/fs/umount", - base = self.fuse_url - ); -@@ -293,7 +312,7 @@ impl Mega { - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client - .post_json( -- "http://127.0.0.1:2725/api/fs/umount", -+ uri.as_str(), - AsyncBody::from(body), - ) - .await -@@ -321,7 +340,6 @@ impl Mega { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -- // FIXME: settings not work, currently - "{base}/api/fs/mpoint", - base = self.fuse_url - ); -@@ -329,7 +347,7 @@ impl Mega { - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client - .get( -- "http://127.0.0.1:2725/api/fs/mpoint", -+ uri.as_str(), - AsyncBody::empty(), - false, - ) -@@ -358,7 +376,6 @@ impl Mega { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -- // FIXME: settings not work, currently - "{base}/api/config", - base = self.fuse_url - ); -@@ -366,7 +383,7 @@ impl Mega { - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client - .get( -- "http://127.0.0.1:2725/api/config", -+ uri.as_str(), - AsyncBody::empty(), - false, - ) -@@ -395,7 +412,6 @@ impl Mega { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!( -- // FIXME: settings not work, currently - "{base}/api/config", - base = self.fuse_url - ); -@@ -409,7 +425,7 @@ impl Mega { - - cx.spawn(|_this, _cx| async move { - if let Ok(mut resp) = client -- .post_json("http://127.0.0.1:2725/api/config", config.into()) -+ .post_json(uri.as_str(), config.into()) - .await - { - if resp.status().is_success() { -diff --git a/crates/mega/src/mega_settings.rs b/crates/mega/src/mega_settings.rs -index 82721208a1..bada5ccd80 100644 ---- a/crates/mega/src/mega_settings.rs -+++ b/crates/mega/src/mega_settings.rs -@@ -17,23 +17,23 @@ pub struct MegaSettingsContent { - /// Url to communicate with mega - /// - /// Default: http://localhost:8000 -- pub mega_url: String, -+ pub mega_url: Option, - /// Url to communicate with fuse - /// - /// Default: http://localhost:2725 -- pub fuse_url: String, -+ pub fuse_url: Option, - /// Default mount point for fuse - /// - /// Default: "/" (for now) -- pub mount_point: PathBuf, -+ pub mount_point: Option, - /// Path for mega executable - /// - /// Default: "mega" (for now) -- pub mega_executable: PathBuf, -+ pub mega_executable: Option, - /// Path for fuse executable - /// - /// Default: "scorpio" (for now) -- pub fuse_executable: PathBuf, -+ pub fuse_executable: Option, - } - - impl Settings for MegaSettings { --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0016-add-heartbeat-to-detect-if-fuse-running.patch b/scripts/zed-intergration/patches/0016-add-heartbeat-to-detect-if-fuse-running.patch deleted file mode 100644 index 73b7f84cd..000000000 --- a/scripts/zed-intergration/patches/0016-add-heartbeat-to-detect-if-fuse-running.patch +++ /dev/null @@ -1,240 +0,0 @@ -From d45f194e2ef79da93b772a28342a37d0b27193cc Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sun, 17 Nov 2024 17:16:58 +0800 -Subject: [PATCH 16/24] add heartbeat to detect if fuse running - ---- - crates/mega/src/mega.rs | 59 +++++++++++++++++++++++++---- - crates/mega_panel/src/mega_panel.rs | 23 ++++++----- - crates/zed/src/main.rs | 1 - - 3 files changed, 64 insertions(+), 19 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index b33c487662..19e9222cf3 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -6,7 +6,6 @@ - // This should be both warrantied by this module and scorpio - // 2. At least one daemon on this machine when zed startup. - // 3. Complete docs. --// 4. Add settings for this module - - use crate::api::{ - ConfigRequest, ConfigResponse, MountRequest, MountResponse, MountsResponse, UmountRequest, -@@ -18,7 +17,7 @@ use futures::channel::oneshot; - use futures::channel::oneshot::Receiver; - use futures::{AsyncReadExt, FutureExt, SinkExt, TryFutureExt}; - use gpui::http_client::{AsyncBody, HttpClient, HttpRequestExt}; --use gpui::{AppContext, Context, EventEmitter, ModelContext, Path}; -+use gpui::{AppContext, Context, EventEmitter, ModelContext, Path, Task}; - use radix_trie::{Trie, TrieCommon}; - use reqwest_client::ReqwestClient; - use schemars::_private::NoSerialize; -@@ -32,6 +31,9 @@ use std::io::Read; - use std::path::PathBuf; - use std::process::Command; - use std::sync::{Arc, RwLock}; -+use std::thread::sleep; -+use std::time::Duration; -+use futures::future::MaybeDone::Future; - - mod api; - mod mega_settings; -@@ -57,6 +59,7 @@ pub struct Mega { - - fuse_running: bool, - fuse_mounted: bool, -+ heartbeat: bool, - - mount_point: Option, - checkout_path: Trie, -@@ -110,6 +113,7 @@ impl Mega { - - fuse_running: false, - fuse_mounted: false, -+ heartbeat: false, - - mount_point, - checkout_path: Default::default(), -@@ -118,8 +122,8 @@ impl Mega { - fuse_url, - http_client: Arc::new(client), - }; -- println!("Mega New: {mega:?}"); - -+ println!("Mega New: {mega:?}"); - mega - } - -@@ -135,6 +139,7 @@ impl Mega { - // So we can assume that fuse has been dead. - this.update(&mut cx, |mega, cx| { - mega.fuse_running = false; -+ mega.fuse_mounted = false; - cx.emit(Event::FuseRunning(false)); - cx.emit(Event::FuseMounted(None)); - }) -@@ -159,6 +164,7 @@ impl Mega { - } else { Ok(()) }.unwrap(); - - // When mount point changed, emit an event. -+ // update mount point if it's none. - if let Ok(Some(config)) = config.await { - this.update(&mut cx, |this, cx| { - let path = PathBuf::from(config.config.mount_path); -@@ -170,6 +176,9 @@ impl Mega { - cx.emit(Event::FuseMounted(this.mount_point.clone())); - } - } -+ } else if this.fuse_running && this.mount_point.is_none() { -+ this.mount_point = Some(path); -+ cx.emit(Event::FuseMounted(this.mount_point.clone())); - } - }) - } else { Ok(()) } -@@ -181,9 +190,16 @@ impl Mega { - (self.fuse_running, self.fuse_mounted) - } - -+ /// ## Toggle Fuse checkouts -+ /// Checkout or un-checkout the paths in zed. -+ /// Does nothing if fuse not running. - pub fn toggle_fuse(&mut self, cx: &mut ModelContext) { - self.update_status(cx); - let paths = &self.checkout_path; -+ -+ if !self.fuse_running { -+ return; -+ } - - if !self.fuse_mounted { - for (_, (p, _)) in paths.iter().enumerate() { -@@ -206,8 +222,7 @@ impl Mega { - } - - self.fuse_mounted = true; -- // FIXME: A configurable path from fuse api is needed. -- cx.emit(Event::FuseMounted(Some(PathBuf::from("/home/neon/dic")))); -+ cx.emit(Event::FuseMounted(self.mount_point.clone())); - } else { - for (_, (p, &n)) in paths.iter().enumerate() { - let path = PathBuf::from(p); // FIXME is there a better way? -@@ -234,10 +249,19 @@ impl Mega { - } - } - -+ /// ## Toggle Fuse Mount -+ /// In fact, we cannot `mount` or `umount` a fuse from zed. -+ /// -+ /// This function only opens up a new scorpio executable if it detects fuse not running. - pub fn toggle_mount(&mut self, cx: &mut ModelContext) { -- // FIXME should be able to restart fuse -- self.fuse_running = !self.fuse_running; -- cx.emit(Event::FuseRunning(self.fuse_running)); -+ // We only start it, not stop it. -+ if !self.fuse_running { -+ let _ = Command::new(self.fuse_executable.as_os_str()) -+ .spawn() -+ .expect("Fuse Executable path not right"); -+ -+ self.update_status(cx); -+ } - } - - pub fn checkout_path( -@@ -447,6 +471,25 @@ impl Mega { - rx - } - -+ pub fn heartbeat(&mut self, cx: &mut ModelContext) { -+ if self.heartbeat { -+ return; -+ } else { -+ self.heartbeat = true; -+ } -+ -+ cx.spawn(|this, mut cx| async move { -+ loop { -+ this.update(&mut cx, |mega, cx| { -+ mega.update_status(cx); -+ }).expect("mega delegate not be dropped"); -+ -+ let dur = Duration::from_secs(30); -+ cx.background_executor().timer(dur).await; -+ } -+ }).detach(); -+ } -+ - pub fn is_path_checkout(&self, path: &String) -> bool { - let set = &self.checkout_path; - set.get_ancestor(path).is_some() -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 5dec15a182..4ea88e5b4c 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -200,7 +200,6 @@ impl MegaPanel { - fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { - let mega_panel = cx.new_view(|cx| { - let mega = workspace.mega(); -- - let focus_handle = cx.focus_handle(); - cx.on_focus(&focus_handle, Self::focus_in).detach(); - -@@ -208,6 +207,10 @@ impl MegaPanel { - cx.subscribe(mega, |this, mega, event, cx| { - // TODO: listen for mega events - }).detach(); -+ -+ mega.update(cx, |this, cx| { -+ this.heartbeat(cx); -+ }); - - Self { - mega_handle: mega.clone(), -@@ -281,6 +284,15 @@ impl MegaPanel { - .id("mega-control-pad") - .size_full() - .children([ -+ encap_btn(Button::new("btn_toggle_mount", "Toggle Fuse Running") -+ .full_width() -+ .icon(IconName::Context) -+ .icon_position(IconPosition::Start) -+ .on_click(cx.listener(|this, _, cx| { -+ this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -+ this.warn_unimplemented(cx); -+ })) -+ ), - encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio Checkouts") - .full_width() - .icon(IconName::Plus) -@@ -289,15 +301,6 @@ impl MegaPanel { - this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); - })) - ), -- // encap_btn(Button::new("btn_toggle_mount", "Toggle Mount") -- // .full_width() -- // .icon(IconName::Context) -- // .icon_position(IconPosition::Start) -- // .on_click(cx.listener(|this, _, cx| { -- // this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -- // this.warn_unimplemented(cx); -- // })) -- // ), - // encap_btn(Button::new("btn_checkout", "Checkout Path") - // .full_width() - // .icon(IconName::Check) -diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs -index 9df417f3e5..f507133200 100644 ---- a/crates/zed/src/main.rs -+++ b/crates/zed/src/main.rs -@@ -26,7 +26,6 @@ use gpui::{ - use http_client::{read_proxy_from_env, Uri}; - use language::LanguageRegistry; - use log::LevelFilter; --use remote::SshConnectionOptions; - use reqwest_client::ReqwestClient; - - use assets::Assets; --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0017-add-commit-button.patch b/scripts/zed-intergration/patches/0017-add-commit-button.patch deleted file mode 100644 index d38324cfc..000000000 --- a/scripts/zed-intergration/patches/0017-add-commit-button.patch +++ /dev/null @@ -1,846 +0,0 @@ -From e14fe02ac8e203261d09a12119a3e19472fb083b Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sun, 17 Nov 2024 21:20:35 +0800 -Subject: [PATCH 17/24] add commit button - ---- - assets/settings/default.json | 2 +- - crates/mega/src/api.rs | 47 +++++ - crates/mega/src/mega.rs | 166 ++++++++---------- - crates/mega_panel/src/mega_panel.rs | 28 --- - crates/project_panel/src/project_panel.rs | 205 +++++++++++++--------- - 5 files changed, 242 insertions(+), 206 deletions(-) - -diff --git a/assets/settings/default.json b/assets/settings/default.json -index 6ea0fff594..466e83655d 100644 ---- a/assets/settings/default.json -+++ b/assets/settings/default.json -@@ -385,7 +385,7 @@ - // Url to communicate with fuse - "fuse_url": "http://localhost:2725", - // Default mount point for fuse -- "mount_point": "/home/neon/projects", -+ "mount_point": "/home/neon/dic", - // Path for mega executable - "mega_executable": "mega", - // Path for fuse executable -diff --git a/crates/mega/src/api.rs b/crates/mega/src/api.rs -index efbf0d1752..3251888e60 100644 ---- a/crates/mega/src/api.rs -+++ b/crates/mega/src/api.rs -@@ -1,5 +1,7 @@ - use serde::{Deserialize, Serialize}; - -+const SUCCESS: &str = "Success"; -+const FAIL : &str = "Fail"; - #[derive(Debug, Deserialize, Serialize)] - pub struct MountRequest<'a> { - pub path: &'a str, -@@ -55,4 +57,49 @@ pub struct ConfigRequest { - pub mega_url: Option, - pub mount_path: Option, - pub store_path: Option, -+} -+ -+pub trait FuseResponse { -+ fn is_resp_succeed(&self) -> bool; -+ fn is_resp_failed(&self) -> bool; -+} -+ -+impl FuseResponse for MountResponse { -+ fn is_resp_succeed(&self) -> bool { -+ self.status.eq(SUCCESS) -+ } -+ -+ fn is_resp_failed(&self) -> bool { -+ self.status.eq(FAIL) -+ } -+} -+ -+impl FuseResponse for MountsResponse { -+ fn is_resp_succeed(&self) -> bool { -+ self.status.eq(SUCCESS) -+ } -+ -+ fn is_resp_failed(&self) -> bool { -+ self.status.eq(FAIL) -+ } -+} -+ -+impl FuseResponse for UmountResponse { -+ fn is_resp_succeed(&self) -> bool { -+ self.status.eq(SUCCESS) -+ } -+ -+ fn is_resp_failed(&self) -> bool { -+ self.status.eq(FAIL) -+ } -+} -+ -+impl FuseResponse for ConfigResponse { -+ fn is_resp_succeed(&self) -> bool { -+ self.status.eq(SUCCESS) -+ } -+ -+ fn is_resp_failed(&self) -> bool { -+ self.status.eq(FAIL) -+ } - } -\ No newline at end of file -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 19e9222cf3..9003361e4f 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -15,6 +15,7 @@ use crate::mega_settings::MegaSettings; - use crate::Event::FuseMounted; - use futures::channel::oneshot; - use futures::channel::oneshot::Receiver; -+use futures::future::MaybeDone::Future; - use futures::{AsyncReadExt, FutureExt, SinkExt, TryFutureExt}; - use gpui::http_client::{AsyncBody, HttpClient, HttpRequestExt}; - use gpui::{AppContext, Context, EventEmitter, ModelContext, Path, Task}; -@@ -33,9 +34,8 @@ use std::process::Command; - use std::sync::{Arc, RwLock}; - use std::thread::sleep; - use std::time::Duration; --use futures::future::MaybeDone::Future; - --mod api; -+pub mod api; - mod mega_settings; - - pub fn init(cx: &mut AppContext) { -@@ -52,6 +52,7 @@ pub enum Event { - struct CheckoutState { - path: PathBuf, - mounted: bool, -+ notify: bool, - } - - pub struct Mega { -@@ -75,11 +76,10 @@ impl EventEmitter for Mega {} - - impl Debug for Mega { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { -- write!(f, -- "fuse_executable: {:?}, mega_url: {}, fuse_url: {}", -- self.fuse_executable, -- self.mega_url, -- self.fuse_url -+ write!( -+ f, -+ "fuse_executable: {:?}, mega_url: {}, fuse_url: {}", -+ self.fuse_executable, self.mega_url, self.fuse_url - ) - } - } -@@ -148,28 +148,32 @@ impl Mega { - // Check if checkout-ed paths are correct - this.update(&mut cx, |mega, cx| { - mega.fuse_running = true; -- -+ - let trie = &mut mega.checkout_path; - for ref i in info.mounts { - let missing = trie.get_ancestor(&i.path).is_none(); - if missing { - // Should not happen unless on startup. - trie.insert(i.path.clone(), i.inode); -- cx.emit(Event::FuseCheckout(Some(PathBuf::from(i.path.clone())))) -+ cx.emit(Event::FuseCheckout(Some(PathBuf::from( -+ i.path.clone(), -+ )))) - } - } - }) - } - } -- } else { Ok(()) }.unwrap(); -+ } else { -+ Ok(()) -+ } -+ .unwrap(); - - // When mount point changed, emit an event. - // update mount point if it's none. - if let Ok(Some(config)) = config.await { - this.update(&mut cx, |this, cx| { - let path = PathBuf::from(config.config.mount_path); -- if (this.fuse_mounted && this.fuse_running) -- && this.mount_point.is_some() { -+ if (this.fuse_mounted && this.fuse_running) && this.mount_point.is_some() { - if let Some(inner) = &this.mount_point { - if !inner.eq(&path) { - this.mount_point = Some(path); -@@ -181,7 +185,9 @@ impl Mega { - cx.emit(Event::FuseMounted(this.mount_point.clone())); - } - }) -- } else { Ok(()) } -+ } else { -+ Ok(()) -+ } - }) - .detach(); - } -@@ -196,7 +202,7 @@ impl Mega { - pub fn toggle_fuse(&mut self, cx: &mut ModelContext) { - self.update_status(cx); - let paths = &self.checkout_path; -- -+ - if !self.fuse_running { - return; - } -@@ -205,9 +211,9 @@ impl Mega { - for (_, (p, _)) in paths.iter().enumerate() { - let path = PathBuf::from(p); // FIXME is there a better way? - cx.spawn(|mega, mut cx| async move { -- let recv = mega.update(&mut cx, |this, cx| { -- this.checkout_path(cx, path) -- }).expect("mega delegate not be dropped"); -+ let recv = mega -+ .update(&mut cx, |this, cx| this.checkout_path(cx, path)) -+ .expect("mega delegate not be dropped"); - - if let Ok(Some(resp)) = recv.await { - mega.update(&mut cx, |this, cx| { -@@ -218,19 +224,20 @@ impl Mega { - Ok(()) - } - }) -- .detach(); -+ .detach(); - } - - self.fuse_mounted = true; - cx.emit(Event::FuseMounted(self.mount_point.clone())); - } else { -- for (_, (p, &n)) in paths.iter().enumerate() { -+ for (_, (p, _)) in paths.iter().enumerate() { - let path = PathBuf::from(p); // FIXME is there a better way? - cx.spawn(|mega, mut cx| async move { -- let recv = mega.update(&mut cx, |this, cx| { -- let param = PathBuf::from(path); -- this.restore_path(cx, param, n) -- }).expect("mega delegate not be dropped"); -+ let recv = mega -+ .update(&mut cx, |this, cx| { -+ this.restore_path(cx, path) -+ }) -+ .expect("mega delegate not be dropped"); - - if let Ok(Some(resp)) = recv.await { - mega.update(&mut cx, |this, cx| { -@@ -241,7 +248,7 @@ impl Mega { - Ok(()) - } - }) -- .detach(); -+ .detach(); - } - - self.fuse_mounted = false; -@@ -251,7 +258,7 @@ impl Mega { - - /// ## Toggle Fuse Mount - /// In fact, we cannot `mount` or `umount` a fuse from zed. -- /// -+ /// - /// This function only opens up a new scorpio executable if it detects fuse not running. - pub fn toggle_mount(&mut self, cx: &mut ModelContext) { - // We only start it, not stop it. -@@ -259,7 +266,7 @@ impl Mega { - let _ = Command::new(self.fuse_executable.as_os_str()) - .spawn() - .expect("Fuse Executable path not right"); -- -+ - self.update_status(cx); - } - } -@@ -271,10 +278,7 @@ impl Mega { - ) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); -- let uri = format!( -- "{base}/api/fs/mount", -- base = self.fuse_url -- ); -+ let uri = format!("{base}/api/fs/mount", base = self.fuse_url); - - // If it panics, that means there's a bug in code. - let path = path.to_str().unwrap(); -@@ -282,13 +286,7 @@ impl Mega { - let body = serde_json::to_string(&req).unwrap(); - - cx.spawn(|_this, _cx| async move { -- if let Ok(mut resp) = client -- .post_json( -- uri.as_str(), -- AsyncBody::from(body), -- ) -- .await -- { -+ if let Ok(mut resp) = client.post_json(uri.as_str(), AsyncBody::from(body)).await { - if resp.status().is_success() { - let mut buf = Vec::new(); - resp.body_mut().read_to_end(&mut buf).await.unwrap(); -@@ -308,39 +306,27 @@ impl Mega { - rx - } - -- pub fn checkout_multi_path(&mut self, cx: &mut ModelContext, mut path: Vec) { -- unimplemented!() -- } -- - pub fn restore_path( - &self, - cx: &ModelContext, - path: PathBuf, -- inode: u64, - ) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); -- let uri = format!( -- "{base}/api/fs/umount", -- base = self.fuse_url -- ); -+ let uri = format!("{base}/api/fs/umount", base = self.fuse_url); - -- // If it panics, that means there's a bug in code. -+ // If panics here, that means there's a bug in code. -+ // maybe we should ensure every path absolute? - let path = path.to_str().unwrap(); -+ let inode = self.checkout_path.get_ancestor_value(path); - let req = UmountRequest { - path: Some(path), -- inode: Some(inode), -+ inode: Some(inode.unwrap().to_owned()), - }; - let body = serde_json::to_string(&req).unwrap(); - - cx.spawn(|_this, _cx| async move { -- if let Ok(mut resp) = client -- .post_json( -- uri.as_str(), -- AsyncBody::from(body), -- ) -- .await -- { -+ if let Ok(mut resp) = client.post_json(uri.as_str(), AsyncBody::from(body)).await { - if resp.status().is_success() { - let mut buf = Vec::new(); - resp.body_mut().read_to_end(&mut buf).await.unwrap(); -@@ -363,20 +349,10 @@ impl Mega { - pub fn get_checkout_paths(&self, cx: &ModelContext) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); -- let uri = format!( -- "{base}/api/fs/mpoint", -- base = self.fuse_url -- ); -+ let uri = format!("{base}/api/fs/mpoint", base = self.fuse_url); - - cx.spawn(|_this, _cx| async move { -- if let Ok(mut resp) = client -- .get( -- uri.as_str(), -- AsyncBody::empty(), -- false, -- ) -- .await -- { -+ if let Ok(mut resp) = client.get(uri.as_str(), AsyncBody::empty(), false).await { - if resp.status().is_success() { - let mut buf = Vec::new(); - resp.body_mut().read_to_end(&mut buf).await.unwrap(); -@@ -399,20 +375,10 @@ impl Mega { - pub fn get_fuse_config(&self, cx: &ModelContext) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); -- let uri = format!( -- "{base}/api/config", -- base = self.fuse_url -- ); -+ let uri = format!("{base}/api/config", base = self.fuse_url); - - cx.spawn(|_this, _cx| async move { -- if let Ok(mut resp) = client -- .get( -- uri.as_str(), -- AsyncBody::empty(), -- false, -- ) -- .await -- { -+ if let Ok(mut resp) = client.get(uri.as_str(), AsyncBody::empty(), false).await { - if resp.status().is_success() { - let mut buf = Vec::new(); - resp.body_mut().read_to_end(&mut buf).await.unwrap(); -@@ -435,10 +401,7 @@ impl Mega { - pub fn set_fuse_config(&self, cx: &mut ModelContext) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); -- let uri = format!( -- "{base}/api/config", -- base = self.fuse_url -- ); -+ let uri = format!("{base}/api/config", base = self.fuse_url); - let config = ConfigRequest { - mega_url: None, - mount_path: None, -@@ -448,10 +411,7 @@ impl Mega { - let config = serde_json::to_string(&config).unwrap(); - - cx.spawn(|_this, _cx| async move { -- if let Ok(mut resp) = client -- .post_json(uri.as_str(), config.into()) -- .await -- { -+ if let Ok(mut resp) = client.post_json(uri.as_str(), config.into()).await { - if resp.status().is_success() { - let mut buf = Vec::new(); - resp.body_mut().read_to_end(&mut buf).await.unwrap(); -@@ -470,28 +430,44 @@ impl Mega { - - rx - } -- -+ - pub fn heartbeat(&mut self, cx: &mut ModelContext) { - if self.heartbeat { - return; - } else { - self.heartbeat = true; - } -- -+ - cx.spawn(|this, mut cx| async move { - loop { - this.update(&mut cx, |mega, cx| { - mega.update_status(cx); -- }).expect("mega delegate not be dropped"); -- -+ }) -+ .expect("mega delegate not be dropped"); -+ - let dur = Duration::from_secs(30); - cx.background_executor().timer(dur).await; - } -- }).detach(); -+ }) -+ .detach(); - } -- -- pub fn is_path_checkout(&self, path: &String) -> bool { -+ -+ pub fn is_path_checkout(&self, path: PathBuf) -> bool { - let set = &self.checkout_path; -- set.get_ancestor(path).is_some() -+ -+ set.get_ancestor(path.to_str().unwrap()).is_some() -+ } -+ -+ pub fn mark_checkout(&mut self, cx: &mut ModelContext, path: String, inode: u64) { -+ if self.mount_point.is_some() { -+ let path = self.mount_point.clone().unwrap().to_str().unwrap().to_string() + path.as_str(); -+ self.checkout_path.insert(path, inode); -+ cx.emit(Event::FuseCheckout(None)); -+ } -+ } -+ -+ pub fn mark_commited(&mut self, cx: &mut ModelContext, path: PathBuf) { -+ self.checkout_path.remove(path.to_str().unwrap()); -+ cx.emit(Event::FuseCheckout(None)); - } - } -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 4ea88e5b4c..142f627ed8 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -290,7 +290,6 @@ impl MegaPanel { - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -- this.warn_unimplemented(cx); - })) - ), - encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio Checkouts") -@@ -301,33 +300,6 @@ impl MegaPanel { - this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); - })) - ), -- // encap_btn(Button::new("btn_checkout", "Checkout Path") -- // .full_width() -- // .icon(IconName::Check) -- // .icon_position(IconPosition::Start) -- // .on_click(cx.listener(|this, _, cx| { -- // this.warn_unimplemented(cx); -- // let options = PathPromptOptions { -- // files: true, -- // directories: true, -- // multiple: false, -- // }; -- // -- // let abs_path = cx.prompt_for_paths(options); -- // -- // // Why so annoying... -- // let mega = this.mega_handle.clone(); -- // cx.spawn(|this, mut cx|async move { -- // // mega.update(&mut cx, |this, cx| async move { -- // // if let Ok(Ok(Some(result))) = abs_path.await { -- // // this.checkout_multi_path(cx, result); -- // // } -- // // }).log_err(); -- // -- // }) .detach(); -- // -- // })) -- // ), - ]) - } - -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index a83346ae60..047c3b0eaa 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -15,6 +15,7 @@ use file_icons::FileIcons; - use anyhow::{anyhow, Context as _, Result}; - use collections::{hash_map, BTreeSet, HashMap}; - use core::f32; -+use db::write_and_log; - use git::repository::GitFileStatus; - use gpui::{ - actions, anchored, deferred, div, impl_actions, px, uniform_list, Action, AnyElement, -@@ -26,6 +27,7 @@ use gpui::{ - WindowContext, - }; - use indexmap::IndexMap; -+use mega::{api::FuseResponse, Mega}; - use menu::{Confirm, SelectFirst, SelectLast, SelectNext, SelectPrev}; - use project::{ - relativize_path, Entry, EntryKind, Fs, Project, ProjectEntryId, ProjectPath, Worktree, -@@ -43,8 +45,6 @@ use std::{ - sync::Arc, - time::Duration, - }; --use db::write_and_log; --use mega::Mega; - use theme::ThemeSettings; - use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem, Tooltip}; - use util::{maybe, ResultExt, TryFutureExt}; -@@ -59,7 +59,6 @@ const PROJECT_PANEL_KEY: &str = "ProjectPanel"; - const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX; - - pub struct ProjectPanel { -- // TODO: use segment tree to fastly store multiple checkout path, - project: Model, - mega: Model, - fs: Arc, -@@ -70,7 +69,6 @@ pub struct ProjectPanel { - /// Relevant only for auto-fold dirs, where a single project panel entry may actually consist of several - /// project entries (and all non-leaf nodes are guaranteed to be directories). - ancestors: HashMap, -- checkout_entry_id: Option, - last_worktree_root_id: Option, - last_external_paths_drag_over_entry: Option, - expanded_dir_ids: HashMap>, -@@ -169,6 +167,7 @@ actions!( - FoldDirectory, - SelectParent, - CheckoutPath, -+ CommitPath, - ] - ); - -@@ -298,19 +297,19 @@ impl ProjectPanel { - cx.spawn(|this, mut cx| async move { - if let Some(task) = this - .update(&mut cx, |this, cx| { -- this.open_workspace_for_paths(false, vec!(path), cx) -+ this.open_workspace_for_paths(false, vec![path], cx) - }) - .log_err() - { - task.await.log_err(); - } - }) -- .detach() -+ .detach() - }) - .log_err(); -- -+ - this.focus_in(cx); -- }, -+ } - mega::Event::FuseMounted(None) => { - // TODO: close the workspace - } -@@ -318,7 +317,8 @@ impl ProjectPanel { - // It's not important, for now. - } - _ => {} -- }).detach(); -+ }) -+ .detach(); - - cx.observe_global::(|_, cx| { - cx.notify(); -@@ -343,7 +343,6 @@ impl ProjectPanel { - focus_handle, - visible_entries: Default::default(), - ancestors: Default::default(), -- checkout_entry_id: Default::default(), - last_worktree_root_id: Default::default(), - last_external_paths_drag_over_entry: None, - expanded_dir_ids: Default::default(), -@@ -519,6 +518,7 @@ impl ProjectPanel { - ) { - let this = cx.view().clone(); - let project = self.project.read(cx); -+ let mega = self.mega.read(cx); - - let worktree_id = if let Some(id) = project.worktree_id_for_entry(entry_id, cx) { - id -@@ -542,6 +542,7 @@ impl ProjectPanel { - let is_read_only = project.is_read_only(cx); - let is_remote = project.is_via_collab() && project.dev_server_project_id().is_none(); - let is_local = project.is_local(); -+ let is_checkout = mega.is_path_checkout(entry.path.to_path_buf()); - - let context_menu = ContextMenu::build(cx, |menu, cx| { - menu.context(self.focus_handle.clone()).map(|menu| { -@@ -550,73 +551,81 @@ impl ProjectPanel { - menu.action("Search Inside", Box::new(NewSearchInDirectory)) - }) - } else { -- menu -- .action("Checkout Path", Box::new(CheckoutPath)) -- .separator() -- .action("New File", Box::new(NewFile)) -- .action("New Folder", Box::new(NewDirectory)) -- .separator() -- .when(is_local && cfg!(target_os = "macos"), |menu| { -- menu.action("Reveal in Finder", Box::new(RevealInFileManager)) -- }) -- .when(is_local && cfg!(not(target_os = "macos")), |menu| { -- menu.action("Reveal in File Manager", Box::new(RevealInFileManager)) -- }) -- .when(is_local, |menu| { -- menu.action("Open in Default App", Box::new(OpenWithSystem)) -- }) -- .action("Open in Terminal", Box::new(OpenInTerminal)) -- .when(is_dir, |menu| { -- menu.separator() -- .action("Find in Folder…", Box::new(NewSearchInDirectory)) -- }) -- .when(is_unfoldable, |menu| { -- menu.action("Unfold Directory", Box::new(UnfoldDirectory)) -- }) -- .when(is_foldable, |menu| { -- menu.action("Fold Directory", Box::new(FoldDirectory)) -- }) -- .separator() -- .action("Cut", Box::new(Cut)) -- .action("Copy", Box::new(Copy)) -- .action("Duplicate", Box::new(Duplicate)) -- // TODO: Paste should always be visible, cbut disabled when clipboard is empty -- .map(|menu| { -- if self.clipboard.as_ref().is_some() { -- menu.action("Paste", Box::new(Paste)) -- } else { -- menu.disabled_action("Paste", Box::new(Paste)) -- } -- }) -- .separator() -- .action("Copy Path", Box::new(CopyPath)) -- .action("Copy Relative Path", Box::new(CopyRelativePath)) -- .separator() -- .action("Rename", Box::new(Rename)) -- .when(!is_root, |menu| { -- menu.action("Trash", Box::new(Trash { skip_prompt: false })) -- .action("Delete", Box::new(Delete { skip_prompt: false })) -- }) -- .when(!is_remote & is_root, |menu| { -- menu.separator() -- .action( -- "Add Folder to Project…", -- Box::new(workspace::AddFolderToProject), -- ) -- .entry( -- "Remove from Project", -- None, -- cx.handler_for(&this, move |this, cx| { -- this.project.update(cx, |project, cx| { -- project.remove_worktree(worktree_id, cx) -- }); -- }), -+ menu.when(!is_checkout && !is_root, |menu| { -+ menu.action("Checkout Path", Box::new(CheckoutPath)) -+ }) -+ .when(is_checkout, |menu| { -+ menu.action("Commit Path", Box::new(CommitPath)) -+ .separator() -+ .action("New File", Box::new(NewFile)) -+ .action("New Folder", Box::new(NewDirectory)) -+ .separator() -+ .when(is_local && cfg!(target_os = "macos"), |menu| { -+ menu.action("Reveal in Finder", Box::new(RevealInFileManager)) -+ }) -+ .when(is_local && cfg!(not(target_os = "macos")), |menu| { -+ menu.action( -+ "Reveal in File Manager", -+ Box::new(RevealInFileManager), - ) -- }) -- .when(is_root, |menu| { -- menu.separator() -- .action("Collapse All", Box::new(CollapseAllEntries)) -- }) -+ }) -+ .when(is_local, |menu| { -+ menu.action("Open in Default App", Box::new(OpenWithSystem)) -+ }) -+ .action("Open in Terminal", Box::new(OpenInTerminal)) -+ .when(is_dir, |menu| { -+ menu.separator() -+ .action("Find in Folder…", Box::new(NewSearchInDirectory)) -+ }) -+ .when(is_unfoldable, |menu| { -+ menu.action("Unfold Directory", Box::new(UnfoldDirectory)) -+ }) -+ .when(is_foldable, |menu| { -+ menu.action("Fold Directory", Box::new(FoldDirectory)) -+ }) -+ .separator() -+ .action("Cut", Box::new(Cut)) -+ .action("Copy", Box::new(Copy)) -+ .action("Duplicate", Box::new(Duplicate)) -+ // TODO: Paste should always be visible, cbut disabled when clipboard is empty -+ .map(|menu| { -+ if self.clipboard.as_ref().is_some() { -+ menu.action("Paste", Box::new(Paste)) -+ } else { -+ menu.disabled_action("Paste", Box::new(Paste)) -+ } -+ }) -+ .separator() -+ .action("Copy Path", Box::new(CopyPath)) -+ .action("Copy Relative Path", Box::new(CopyRelativePath)) -+ .separator() -+ // Fuse not support renaming, currently. -+ // .action("Rename", Box::new(Rename)) -+ .when(!is_root, |menu| { -+ menu.action("Trash", Box::new(Trash { skip_prompt: false })) -+ .action("Delete", Box::new(Delete { skip_prompt: false })) -+ }) -+ .when(!is_remote & is_root, |menu| { -+ menu.separator() -+ .action( -+ "Add Folder to Project…", -+ Box::new(workspace::AddFolderToProject), -+ ) -+ .entry( -+ "Remove from Project", -+ None, -+ cx.handler_for(&this, move |this, cx| { -+ this.project.update(cx, |project, cx| { -+ project.remove_worktree(worktree_id, cx) -+ }); -+ }), -+ ) -+ }) -+ .when(is_root, |menu| { -+ menu.separator() -+ .action("Collapse All", Box::new(CollapseAllEntries)) -+ }) -+ }) - } - }) - }); -@@ -1340,11 +1349,42 @@ impl ProjectPanel { - if let Some((worktree, entry)) = self.selected_entry_handle(cx) { - let path = entry.path.clone(); - self.mega.update(cx, |mega, cx| { -- let recv = mega.checkout_path(cx, path.to_path_buf()); -- cx.spawn(|_, _| async move { -+ let recv = mega.checkout_path(cx, path.to_path_buf()); -+ cx.spawn(|this, mut cx| async move { -+ let resp = recv.await; -+ println!("Response: {resp:?}"); -+ if let Ok(Some(resp)) = resp { -+ if resp.is_resp_succeed() { -+ this.update(&mut cx, |mega, cx| { -+ mega.mark_checkout(cx, resp.mount.path, resp.mount.inode); -+ }) -+ .expect("Mega delegate not been dropped"); -+ } -+ } -+ }) -+ .detach(); -+ }); -+ } -+ } -+ -+ fn commit_specific_path(&mut self, _: &CommitPath, cx: &mut ViewContext) { -+ if let Some((worktree, entry)) = self.selected_entry_handle(cx) { -+ let path = entry.path.clone(); -+ self.mega.update(cx, |mega, cx| { -+ let recv = mega.restore_path(cx, path.to_path_buf()); -+ cx.spawn(|this, mut cx| async move { - let resp = recv.await; - println!("Response: {resp:?}"); -- }).detach(); -+ if let Ok(Some(resp)) = resp { -+ if resp.is_resp_succeed() { -+ this.update(&mut cx, |mega, cx| { -+ mega.mark_commited(cx, path.to_path_buf()); -+ }) -+ .expect("Mega delegate not been dropped"); -+ } -+ } -+ }) -+ .detach(); - }); - } - } -@@ -2358,6 +2398,7 @@ impl ProjectPanel { - details: EntryDetails, - cx: &mut ViewContext, - ) -> Stateful
{ -+ let mega = self.mega.read(cx); - let kind = details.kind; - let settings = ProjectPanelSettings::get_global(cx); - let show_editor = details.is_editing && !details.is_processing; -@@ -2370,7 +2411,7 @@ impl ProjectPanel { - .selection - .map_or(false, |selection| selection.entry_id == entry_id); - let width = self.size(cx); -- let filename_text_color = -+ let filename_text_color = - entry_git_aware_label_color(details.git_status, details.is_ignored, is_marked); - let file_name = details.filename.clone(); - let mut icon = details.icon.clone(); -@@ -2963,6 +3004,7 @@ impl Render for ProjectPanel { - .on_action(cx.listener(Self::unfold_directory)) - .on_action(cx.listener(Self::fold_directory)) - .on_action(cx.listener(Self::checkout_specific_path)) -+ .on_action(cx.listener(Self::commit_specific_path)) - .when(!project.is_read_only(cx), |el| { - el.on_action(cx.listener(Self::new_file)) - .on_action(cx.listener(Self::new_directory)) -@@ -3057,8 +3099,7 @@ impl Render for ProjectPanel { - // .update(cx, |workspace, cx| workspace.open(&workspace::Open, cx)) - // .log_err(); - // })), -- Label::new("Run mega daemon to mount the working directories") -- -+ Label::new("Run mega daemon to mount the working directories"), - ) - .drag_over::(|style, _, cx| { - style.bg(cx.theme().colors().drop_target_background) --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0018-adjust-context-menu-for-fuse.patch b/scripts/zed-intergration/patches/0018-adjust-context-menu-for-fuse.patch deleted file mode 100644 index dfd85ce3f..000000000 --- a/scripts/zed-intergration/patches/0018-adjust-context-menu-for-fuse.patch +++ /dev/null @@ -1,104 +0,0 @@ -From cc5def5cd4729cb1705c01896710157e43c0829d Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sun, 17 Nov 2024 21:39:21 +0800 -Subject: [PATCH 18/24] adjust context menu for fuse - ---- - crates/project_panel/src/project_panel.rs | 57 +++++++++++------------ - 1 file changed, 27 insertions(+), 30 deletions(-) - -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index 047c3b0eaa..baec6a00a5 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -15,7 +15,6 @@ use file_icons::FileIcons; - use anyhow::{anyhow, Context as _, Result}; - use collections::{hash_map, BTreeSet, HashMap}; - use core::f32; --use db::write_and_log; - use git::repository::GitFileStatus; - use gpui::{ - actions, anchored, deferred, div, impl_actions, px, uniform_list, Action, AnyElement, -@@ -587,7 +586,7 @@ impl ProjectPanel { - .action("Cut", Box::new(Cut)) - .action("Copy", Box::new(Copy)) - .action("Duplicate", Box::new(Duplicate)) -- // TODO: Paste should always be visible, cbut disabled when clipboard is empty -+ // TODO: Paste should always be visible, but disabled when clipboard is empty - .map(|menu| { - if self.clipboard.as_ref().is_some() { - menu.action("Paste", Box::new(Paste)) -@@ -599,32 +598,30 @@ impl ProjectPanel { - .action("Copy Path", Box::new(CopyPath)) - .action("Copy Relative Path", Box::new(CopyRelativePath)) - .separator() -- // Fuse not support renaming, currently. -- // .action("Rename", Box::new(Rename)) -- .when(!is_root, |menu| { -- menu.action("Trash", Box::new(Trash { skip_prompt: false })) -- .action("Delete", Box::new(Delete { skip_prompt: false })) -- }) -- .when(!is_remote & is_root, |menu| { -- menu.separator() -- .action( -- "Add Folder to Project…", -- Box::new(workspace::AddFolderToProject), -- ) -- .entry( -- "Remove from Project", -- None, -- cx.handler_for(&this, move |this, cx| { -- this.project.update(cx, |project, cx| { -- project.remove_worktree(worktree_id, cx) -- }); -- }), -- ) -- }) -- .when(is_root, |menu| { -- menu.separator() -- .action("Collapse All", Box::new(CollapseAllEntries)) -- }) -+ .action("Trash", Box::new(Trash { skip_prompt: false })) -+ .action("Delete", Box::new(Delete { skip_prompt: false })) -+ // Fuse not support renaming, currently. -+ // .action("Rename", Box::new(Rename)) -+ }) -+ .when(!is_remote & is_root, |menu| { -+ menu -+ .action( -+ "Add Folder to Project…", -+ Box::new(workspace::AddFolderToProject), -+ ) -+ .entry( -+ "Remove from Project", -+ None, -+ cx.handler_for(&this, move |this, cx| { -+ this.project.update(cx, |project, cx| { -+ project.remove_worktree(worktree_id, cx) -+ }); -+ }), -+ ) -+ }) -+ .when(is_root, |menu| { -+ menu.separator() -+ .action("Collapse All", Box::new(CollapseAllEntries)) - }) - } - }) -@@ -1380,11 +1377,11 @@ impl ProjectPanel { - this.update(&mut cx, |mega, cx| { - mega.mark_commited(cx, path.to_path_buf()); - }) -- .expect("Mega delegate not been dropped"); -+ .expect("Mega delegate not been dropped"); - } - } - }) -- .detach(); -+ .detach(); - }); - } - } --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0019-fix-warnings.patch b/scripts/zed-intergration/patches/0019-fix-warnings.patch deleted file mode 100644 index 688996ba1..000000000 --- a/scripts/zed-intergration/patches/0019-fix-warnings.patch +++ /dev/null @@ -1,164 +0,0 @@ -From f205678bc18d6b7b1ffc57aa923120348271623b Mon Sep 17 00:00:00 2001 -From: Neon -Date: Sun, 17 Nov 2024 22:07:53 +0800 -Subject: [PATCH 19/24] fix warnings - ---- - crates/mega/src/mega.rs | 44 ++++++++--------------- - crates/project_panel/src/project_panel.rs | 13 ++++--- - 2 files changed, 20 insertions(+), 37 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 9003361e4f..2d85052e63 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -1,38 +1,20 @@ --// This crate delegate mega and its fuse daemon. --// The following requirements should be met: --// --// TODO: --// 1. Only one daemon on this machine. --// This should be both warrantied by this module and scorpio --// 2. At least one daemon on this machine when zed startup. --// 3. Complete docs. -- - use crate::api::{ - ConfigRequest, ConfigResponse, MountRequest, MountResponse, MountsResponse, UmountRequest, - UmountResponse, - }; - use crate::mega_settings::MegaSettings; --use crate::Event::FuseMounted; - use futures::channel::oneshot; - use futures::channel::oneshot::Receiver; --use futures::future::MaybeDone::Future; --use futures::{AsyncReadExt, FutureExt, SinkExt, TryFutureExt}; --use gpui::http_client::{AsyncBody, HttpClient, HttpRequestExt}; --use gpui::{AppContext, Context, EventEmitter, ModelContext, Path, Task}; -+use futures::AsyncReadExt; -+use gpui::http_client::{AsyncBody, HttpClient}; -+use gpui::{AppContext, EventEmitter, ModelContext}; - use radix_trie::{Trie, TrieCommon}; - use reqwest_client::ReqwestClient; --use schemars::_private::NoSerialize; --use serde::Serialize; - use settings::Settings; --use std::collections::{BTreeMap, BTreeSet, HashSet}; --use std::ffi::OsStr; - use std::fmt::{Debug, Formatter}; --use std::hash::{DefaultHasher, Hash, Hasher}; --use std::io::Read; - use std::path::PathBuf; - use std::process::Command; --use std::sync::{Arc, RwLock}; --use std::thread::sleep; -+use std::sync::Arc; - use std::time::Duration; - - pub mod api; -@@ -234,12 +216,10 @@ impl Mega { - let path = PathBuf::from(p); // FIXME is there a better way? - cx.spawn(|mega, mut cx| async move { - let recv = mega -- .update(&mut cx, |this, cx| { -- this.restore_path(cx, path) -- }) -+ .update(&mut cx, |this, cx| this.restore_path(cx, path)) - .expect("mega delegate not be dropped"); - -- if let Ok(Some(resp)) = recv.await { -+ if let Ok(Some(_resp)) = recv.await { - mega.update(&mut cx, |this, cx| { - // TODO use a new check out state struct - cx.emit(Event::FuseCheckout(None)); -@@ -250,9 +230,6 @@ impl Mega { - }) - .detach(); - } -- -- self.fuse_mounted = false; -- cx.emit(Event::FuseMounted(None)); - } - } - -@@ -460,7 +437,14 @@ impl Mega { - - pub fn mark_checkout(&mut self, cx: &mut ModelContext, path: String, inode: u64) { - if self.mount_point.is_some() { -- let path = self.mount_point.clone().unwrap().to_str().unwrap().to_string() + path.as_str(); -+ let path = self -+ .mount_point -+ .clone() -+ .unwrap() -+ .to_str() -+ .unwrap() -+ .to_string() -+ + path.as_str(); - self.checkout_path.insert(path, inode); - cx.emit(Event::FuseCheckout(None)); - } -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index baec6a00a5..70ad294cd9 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -45,7 +45,7 @@ use std::{ - time::Duration, - }; - use theme::ThemeSettings; --use ui::{prelude::*, v_flex, ContextMenu, Icon, KeyBinding, Label, ListItem, Tooltip}; -+use ui::{prelude::*, v_flex, ContextMenu, Icon, Label, ListItem, Tooltip}; - use util::{maybe, ResultExt, TryFutureExt}; - use workspace::{ - dock::{DockPosition, Panel, PanelEvent}, -@@ -287,12 +287,12 @@ impl ProjectPanel { - ) - .detach(); - -- cx.subscribe(&mega, |this, mega, mega_event, cx| match mega_event { -+ cx.subscribe(&mega, |this, _, mega_event, cx| match mega_event { - mega::Event::FuseMounted(Some(path)) => { - println!("Fuse Mounted: {path:?}"); - let path = path.to_owned(); - this.workspace -- .update(cx, |workspace, cx| { -+ .update(cx, |_, cx| { - cx.spawn(|this, mut cx| async move { - if let Some(task) = this - .update(&mut cx, |this, cx| { -@@ -312,7 +312,7 @@ impl ProjectPanel { - mega::Event::FuseMounted(None) => { - // TODO: close the workspace - } -- mega::Event::FuseCheckout(path) => { -+ mega::Event::FuseCheckout(_path) => { - // It's not important, for now. - } - _ => {} -@@ -1343,7 +1343,7 @@ impl ProjectPanel { - } - - fn checkout_specific_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { -- if let Some((worktree, entry)) = self.selected_entry_handle(cx) { -+ if let Some((_, entry)) = self.selected_entry_handle(cx) { - let path = entry.path.clone(); - self.mega.update(cx, |mega, cx| { - let recv = mega.checkout_path(cx, path.to_path_buf()); -@@ -1365,7 +1365,7 @@ impl ProjectPanel { - } - - fn commit_specific_path(&mut self, _: &CommitPath, cx: &mut ViewContext) { -- if let Some((worktree, entry)) = self.selected_entry_handle(cx) { -+ if let Some((_, entry)) = self.selected_entry_handle(cx) { - let path = entry.path.clone(); - self.mega.update(cx, |mega, cx| { - let recv = mega.restore_path(cx, path.to_path_buf()); -@@ -2395,7 +2395,6 @@ impl ProjectPanel { - details: EntryDetails, - cx: &mut ViewContext, - ) -> Stateful
{ -- let mega = self.mega.read(cx); - let kind = details.kind; - let settings = ProjectPanelSettings::get_global(cx); - let show_editor = details.is_editing && !details.is_processing; --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0020-fix-crate-collab-compile-error-with-mega.patch b/scripts/zed-intergration/patches/0020-fix-crate-collab-compile-error-with-mega.patch deleted file mode 100644 index c9f359269..000000000 --- a/scripts/zed-intergration/patches/0020-fix-crate-collab-compile-error-with-mega.patch +++ /dev/null @@ -1,82 +0,0 @@ -From bcb691e423f44aadc34837d514e61bb23f86b32a Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 19 Nov 2024 09:36:55 +0800 -Subject: [PATCH 20/24] fix crate/collab compile error with mega - ---- - Cargo.lock | 1 + - crates/collab/Cargo.toml | 1 + - crates/collab/src/tests/test_server.rs | 5 +++++ - 3 files changed, 7 insertions(+) - -diff --git a/Cargo.lock b/Cargo.lock -index 0483c524c4..a69e9c68c9 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -2569,6 +2569,7 @@ dependencies = [ - "live_kit_server", - "log", - "lsp", -+ "mega", - "menu", - "multi_buffer", - "nanoid", -diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml -index ad2c013668..78dcfb30ec 100644 ---- a/crates/collab/Cargo.toml -+++ b/crates/collab/Cargo.toml -@@ -101,6 +101,7 @@ language = { workspace = true, features = ["test-support"] } - language_model = { workspace = true, features = ["test-support"] } - live_kit_client = { workspace = true, features = ["test-support"] } - lsp = { workspace = true, features = ["test-support"] } -+mega.workspace = true - menu.workspace = true - multi_buffer = { workspace = true, features = ["test-support"] } - node_runtime.workspace = true -diff --git a/crates/collab/src/tests/test_server.rs b/crates/collab/src/tests/test_server.rs -index 210a049e0b..bb9fb96f70 100644 ---- a/crates/collab/src/tests/test_server.rs -+++ b/crates/collab/src/tests/test_server.rs -@@ -44,6 +44,7 @@ use std::{ - Arc, - }, - }; -+use mega::Mega; - use workspace::{Workspace, WorkspaceStore}; - - pub struct TestServer { -@@ -271,6 +272,7 @@ impl TestServer { - let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx)); - let language_registry = Arc::new(LanguageRegistry::test(cx.executor())); - let session = cx.new_model(|cx| AppSession::new(Session::test(), cx)); -+ let mega = cx.new_model(|cx| Mega::new(cx)); - let app_state = Arc::new(workspace::AppState { - client: client.clone(), - user_store: user_store.clone(), -@@ -280,6 +282,7 @@ impl TestServer { - build_window_options: |_, _| Default::default(), - node_runtime: NodeRuntime::unavailable(), - session, -+ mega, - }); - - let os_keymap = "keymaps/default-macos.json"; -@@ -401,6 +404,7 @@ impl TestServer { - let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx)); - let language_registry = Arc::new(LanguageRegistry::test(cx.executor())); - let session = cx.new_model(|cx| AppSession::new(Session::test(), cx)); -+ let mega = cx.new_model(|cx| Mega::new(cx)); - let app_state = Arc::new(workspace::AppState { - client: client.clone(), - user_store: user_store.clone(), -@@ -410,6 +414,7 @@ impl TestServer { - build_window_options: |_, _| Default::default(), - node_runtime: NodeRuntime::unavailable(), - session, -+ mega, - }); - - cx.update(|cx| { --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0021-improve-code-quality-format-and-fix-warnings.patch b/scripts/zed-intergration/patches/0021-improve-code-quality-format-and-fix-warnings.patch deleted file mode 100644 index 8ee972ccd..000000000 --- a/scripts/zed-intergration/patches/0021-improve-code-quality-format-and-fix-warnings.patch +++ /dev/null @@ -1,401 +0,0 @@ -From 7b8bce244556a88a95672ffa79cfc21fb0da2efe Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 19 Nov 2024 11:13:48 +0800 -Subject: [PATCH 21/24] improve code quality, format and fix warnings - ---- - crates/mega/src/mega.rs | 16 ++- - crates/mega/src/utils.rs | 1 + - crates/mega/src/{ => utils}/api.rs | 0 - crates/mega_panel/src/mega_panel.rs | 171 ++++++++++++++-------------- - 4 files changed, 92 insertions(+), 96 deletions(-) - create mode 100644 crates/mega/src/utils.rs - rename crates/mega/src/{ => utils}/api.rs (100%) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 2d85052e63..abc46f1651 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -1,4 +1,4 @@ --use crate::api::{ -+use utils::api::{ - ConfigRequest, ConfigResponse, MountRequest, MountResponse, MountsResponse, UmountRequest, - UmountResponse, - }; -@@ -17,8 +17,8 @@ use std::process::Command; - use std::sync::Arc; - use std::time::Duration; - --pub mod api; - mod mega_settings; -+pub mod utils; - - pub fn init(cx: &mut AppContext) { - Mega::init(cx); -@@ -31,6 +31,7 @@ pub enum Event { - FuseCheckout(Option), - } - -+#[allow(unused)] - struct CheckoutState { - path: PathBuf, - mounted: bool, -@@ -90,7 +91,7 @@ impl Mega { - None - }; - -- let mega = Mega { -+ Mega { - fuse_executable, - - fuse_running: false, -@@ -103,10 +104,7 @@ impl Mega { - mega_url, - fuse_url, - http_client: Arc::new(client), -- }; -- -- println!("Mega New: {mega:?}"); -- mega -+ } - } - - pub fn update_status(&mut self, cx: &mut ModelContext) { -@@ -198,7 +196,7 @@ impl Mega { - .expect("mega delegate not be dropped"); - - if let Ok(Some(resp)) = recv.await { -- mega.update(&mut cx, |this, cx| { -+ mega.update(&mut cx, |_, cx| { - let buf = PathBuf::from(resp.mount.path.clone()); - cx.emit(Event::FuseCheckout(Some(buf))); - }) -@@ -220,7 +218,7 @@ impl Mega { - .expect("mega delegate not be dropped"); - - if let Ok(Some(_resp)) = recv.await { -- mega.update(&mut cx, |this, cx| { -+ mega.update(&mut cx, |_, cx| { - // TODO use a new check out state struct - cx.emit(Event::FuseCheckout(None)); - }) -diff --git a/crates/mega/src/utils.rs b/crates/mega/src/utils.rs -new file mode 100644 -index 0000000000..e5fdf85eed ---- /dev/null -+++ b/crates/mega/src/utils.rs -@@ -0,0 +1 @@ -+pub mod api; -diff --git a/crates/mega/src/api.rs b/crates/mega/src/utils/api.rs -similarity index 100% -rename from crates/mega/src/api.rs -rename to crates/mega/src/utils/api.rs -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index 142f627ed8..c5105988e0 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -1,18 +1,25 @@ --use std::path::PathBuf; - use crate::mega_panel_settings::{MegaPanelDockPosition, MegaPanelSettings}; - use anyhow::{anyhow, Context}; - use db::kvp::KEY_VALUE_STORE; - use fs::Fs; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; --use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, EventEmitter, Flatten, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement, PathPromptOptions, Pixels, PromptLevel, Render, SharedString, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext}; -+use gpui::{ -+ actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, -+ EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, -+ ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, Styled, Task -+ , View, ViewContext, VisualContext, WeakView, WindowContext, -+}; - use mega::Mega; - use settings::Settings; - use std::sync::Arc; - use text::BufferId; - use util::{ResultExt, TryFutureExt}; - use workspace::dock::{DockPosition, Panel, PanelEvent}; --use workspace::ui::{h_flex, v_flex, Button, Clickable, Color, FixedWidth, IconName, IconPosition, Label, LabelCommon, LabelSize, StyledExt, StyledTypography}; -+use workspace::ui::{ -+ h_flex, v_flex, Button, Clickable, Color, FixedWidth, IconName, IconPosition, Label, -+ LabelCommon, LabelSize, StyledExt, StyledTypography, -+}; - use workspace::Workspace; - use worktree::{ProjectEntryId, WorktreeId}; - -@@ -20,22 +27,15 @@ mod mega_panel_settings; - - const MEGA_PANEL_KEY: &str = "MegaPanel"; - --actions!( -- mega_panel, -- [ -- ToggleFocus, -- ToggleFuseMount, -- CheckoutPath, -- ] --); -+actions!(mega_panel, [ToggleFocus, ToggleFuseMount, CheckoutPath,]); - - pub struct MegaPanel { - mega_handle: Model, -- workspace: WeakView, -+ // workspace: WeakView, - focus_handle: FocusHandle, -- scroll_handle: UniformListScrollHandle, -+ // scroll_handle: UniformListScrollHandle, - fs: Arc, -- pending_serialization: Task>, // TODO check how to use it -+ pending_serialization: Task>, - width: Option, - } - -@@ -44,6 +44,7 @@ struct SerializedMegaPanel { - width: Option, - } - -+#[allow(unused)] - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] - enum MegaEntry { - Dir(WorktreeId, ProjectEntryId), -@@ -68,7 +69,7 @@ pub fn init(assets: impl AssetSource, cx: &mut AppContext) { - workspace.toggle_panel_focus::(cx); - }); - }) -- .detach(); -+ .detach(); - } - - impl EventEmitter for MegaPanel {} -@@ -91,7 +92,8 @@ impl Render for MegaPanel { - Label::new("Mega Control Panel") - .single_line() - .weight(FontWeight::BOLD) -- .size(LabelSize::Large)) -+ .size(LabelSize::Large), -+ ), - ) - .child(horizontal_separator(cx)) - .child(self.render_status(cx)) -@@ -182,19 +184,16 @@ impl MegaPanel { - .log_err() - .flatten(); - -- workspace.update( -- &mut cx, -- |workspace, cx| { -- let panel = MegaPanel::new(workspace, cx); -- if let Some(serialized_panel) = serialized_panel { -- panel.update(cx, |panel, cx| { -- panel.width = serialized_panel.width.map(|px| px.round()); -- cx.notify(); -- }); -- } -- panel -- }, -- ) -+ workspace.update(&mut cx, |workspace, cx| { -+ let panel = MegaPanel::new(workspace, cx); -+ if let Some(serialized_panel) = serialized_panel { -+ panel.update(cx, |panel, cx| { -+ panel.width = serialized_panel.width.map(|px| px.round()); -+ cx.notify(); -+ }); -+ } -+ panel -+ }) - } - - fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { -@@ -206,17 +205,18 @@ impl MegaPanel { - #[allow(unused)] - cx.subscribe(mega, |this, mega, event, cx| { - // TODO: listen for mega events -- }).detach(); -- -+ }) -+ .detach(); -+ - mega.update(cx, |this, cx| { - this.heartbeat(cx); - }); - - Self { - mega_handle: mega.clone(), -- workspace: workspace.weak_handle(), -+ // workspace: workspace.weak_handle(), - focus_handle, -- scroll_handle: UniformListScrollHandle::new(), -+ // scroll_handle: UniformListScrollHandle::new(), - fs: workspace.app_state().fs.clone(), - pending_serialization: Task::ready(None), - width: None, -@@ -238,7 +238,7 @@ impl MegaPanel { - .await?; - anyhow::Ok(()) - } -- .log_err(), -+ .log_err(), - ); - } - -@@ -251,77 +251,78 @@ impl MegaPanel { - pub fn checkout_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { - self.warn_unimplemented(cx); - } -- -+ - pub fn toggle_fuse_mount(&mut self, _: &ToggleFuseMount, cx: &mut ViewContext) { -- self.mega_handle.update(cx, |this, cx | { -+ self.mega_handle.update(cx, |this, cx| { - this.toggle_mount(cx); - }); - } - - fn render_status(&mut self, cx: &mut ViewContext) -> Div { -- let ( -- fuse_running, -- fuse_mounted -- ) = self.mega_handle.read(cx).status(); -- -- v_flex() -- .gap_1() -- .children([ -- self.status_unit(cx, "Scorpio Backend:", fuse_running), -- self.status_unit(cx, "Fuse Mounted:", fuse_mounted), -- ]) -+ let (fuse_running, fuse_mounted) = self.mega_handle.read(cx).status(); -+ -+ v_flex().gap_1().children([ -+ self.status_unit(cx, "Scorpio Backend:", fuse_running), -+ self.status_unit(cx, "Fuse Mounted:", fuse_mounted), -+ ]) - } - - fn render_buttons(&mut self, cx: &mut ViewContext) -> impl IntoElement { - fn encap_btn(btn: Button) -> Div { -- div() -- .m_1() -- .border_1() -- .child(btn) -+ div().m_1().border_1().child(btn) - } -- -- v_flex() -- .id("mega-control-pad") -- .size_full() -- .children([ -- encap_btn(Button::new("btn_toggle_mount", "Toggle Fuse Running") -+ -+ v_flex().id("mega-control-pad").size_full().children([ -+ encap_btn( -+ Button::new("btn_toggle_mount", "Toggle Fuse Running") - .full_width() - .icon(IconName::Context) - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { -- this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); -- })) -- ), -- encap_btn(Button::new("btn_toggle_scorpio", "Toggle Scorpio Checkouts") -+ this.mega_handle -+ .update(cx, |mega, cx| mega.toggle_mount(cx)); -+ })), -+ ), -+ encap_btn( -+ Button::new("btn_toggle_scorpio", "Toggle Scorpio Checkouts") - .full_width() - .icon(IconName::Plus) - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { - this.mega_handle.update(cx, |mega, cx| mega.toggle_fuse(cx)); -- })) -- ), -- ]) -+ })), -+ ), -+ ]) - } - -- fn status_unit(&self, cx: &mut ViewContext, name: &'static str, state: bool) -> Stateful
{ -+ fn status_unit( -+ &self, -+ cx: &mut ViewContext, -+ name: &'static str, -+ state: bool, -+ ) -> Stateful
{ - let unit_id = ElementId::from(SharedString::from(format!("status_{}", name))); -- div() -- .text_ui(cx) -- .id(unit_id) -- .child( -- h_flex() -- .justify_between() -- .child(Label::new(name)) -- .child(match state { -- true => Label::new("Active").color(Color::Success), -- false => Label::new("Inactive").color(Color::Error) -- }) -- ) -+ div().text_ui(cx).id(unit_id).child( -+ h_flex() -+ .justify_between() -+ .child(Label::new(name)) -+ .child(match state { -+ true => Label::new("Active").color(Color::Success), -+ false => Label::new("Inactive").color(Color::Error), -+ }), -+ ) - } - - fn warn_unimplemented(&self, cx: &mut ViewContext) { -- let message = String::from("This operation is not implemented yet, functions may not behave correctly"); -- let _ = cx.prompt(PromptLevel::Warning, "Unimplemented", Some(&message), &["Got it"]); -+ let message = String::from( -+ "This operation is not implemented yet, functions may not behave correctly", -+ ); -+ let _ = cx.prompt( -+ PromptLevel::Warning, -+ "Unimplemented", -+ Some(&message), -+ &["Got it"], -+ ); - } - } - -@@ -331,10 +332,7 @@ fn horizontal_separator(cx: &mut WindowContext) -> Div { - - #[cfg(test)] - mod tests { -- use std::future::Future; -- use db::smol::future::FutureExt; -- use super::*; -- use gpui::{TestAppContext, VisualTestContext}; -+ use gpui::TestAppContext; - use workspace::AppState; - - #[gpui::test] -@@ -344,7 +342,7 @@ mod tests { - mega::init(cx); - state - }); -- -+ - state.mega.update(cx, |this, cx| { - let recv = this.get_fuse_config(cx); - cx.spawn(|_this, _cx| async move { -@@ -354,9 +352,8 @@ mod tests { - eprintln!("{config:?}"); - } - } -- }).detach(); -+ }) -+ .detach(); - }); -- - } -- - } --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0022-improve-context-button-display.patch b/scripts/zed-intergration/patches/0022-improve-context-button-display.patch deleted file mode 100644 index 0970a4124..000000000 --- a/scripts/zed-intergration/patches/0022-improve-context-button-display.patch +++ /dev/null @@ -1,592 +0,0 @@ -From e16d73a6bda38e6eeced4d6fabc403acd3f0eaeb Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 19 Nov 2024 19:31:44 +0800 -Subject: [PATCH 22/24] improve context button display - ---- - Cargo.lock | 1 + - crates/mega/Cargo.toml | 1 + - crates/mega/src/mega.rs | 162 ++++++++++--------- - crates/mega/src/mega_settings.rs | 6 +- - crates/mega/src/utils/api.rs | 6 +- - crates/mega_panel/src/mega_panel.rs | 19 ++- - crates/mega_panel/src/mega_panel_settings.rs | 6 +- - crates/project_panel/src/project_panel.rs | 65 +++++--- - 8 files changed, 155 insertions(+), 111 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index a69e9c68c9..0671471f30 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -6899,6 +6899,7 @@ dependencies = [ - "bytes 1.7.2", - "futures 0.3.30", - "gpui", -+ "log", - "radix_trie", - "reqwest_client", - "schemars", -diff --git a/crates/mega/Cargo.toml b/crates/mega/Cargo.toml -index a9a4f9d9b7..8c5596d677 100644 ---- a/crates/mega/Cargo.toml -+++ b/crates/mega/Cargo.toml -@@ -23,3 +23,4 @@ bytes.workspace = true - schemars.workspace = true - anyhow.workspace = true - radix_trie.workspace = true -+log.workspace = true -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index abc46f1651..628fe311d9 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -1,21 +1,23 @@ --use utils::api::{ -- ConfigRequest, ConfigResponse, MountRequest, MountResponse, MountsResponse, UmountRequest, -- UmountResponse, --}; - use crate::mega_settings::MegaSettings; - use futures::channel::oneshot; - use futures::channel::oneshot::Receiver; - use futures::AsyncReadExt; - use gpui::http_client::{AsyncBody, HttpClient}; --use gpui::{AppContext, EventEmitter, ModelContext}; -+use gpui::{hash, AppContext, EventEmitter, ModelContext}; - use radix_trie::{Trie, TrieCommon}; - use reqwest_client::ReqwestClient; - use settings::Settings; -+use std::collections::BTreeSet; - use std::fmt::{Debug, Formatter}; --use std::path::PathBuf; -+use std::io::BufWriter; -+use std::path::{Path, PathBuf}; - use std::process::Command; - use std::sync::Arc; - use std::time::Duration; -+use utils::api::{ -+ ConfigRequest, ConfigResponse, MountRequest, MountResponse, MountsResponse, UmountRequest, -+ UmountResponse, -+}; - - mod mega_settings; - pub mod utils; -@@ -46,7 +48,8 @@ pub struct Mega { - heartbeat: bool, - - mount_point: Option, -- checkout_path: Trie, -+ checkout_lut: Trie, -+ checkout_path: BTreeSet, - - mega_url: String, - fuse_url: String, -@@ -59,10 +62,13 @@ impl EventEmitter for Mega {} - - impl Debug for Mega { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { -+ let lut = self.checkout_lut.keys().map(|key| key.to_path_buf()).collect::>(); -+ - write!( - f, -- "fuse_executable: {:?}, mega_url: {}, fuse_url: {}", -- self.fuse_executable, self.mega_url, self.fuse_url -+ "fuse_executable: {:?}, mega_url: {}, fuse_url: {}\n\ -+ LUT: {:?}", -+ self.fuse_executable, self.mega_url, self.fuse_url, lut - ) - } - } -@@ -85,12 +91,15 @@ impl Mega { - // To not affected by global proxy settings. - let client = ReqwestClient::new(); - -+ println!("Mount point: {mount_path:?}"); -+ - let mount_point = if mount_path.exists() { - Some(mount_path) - } else { -+ log::error!("Mount point in setting does not exist"); - None - }; -- -+ - Mega { - fuse_executable, - -@@ -99,6 +108,7 @@ impl Mega { - heartbeat: false, - - mount_point, -+ checkout_lut: Trie::default(), - checkout_path: Default::default(), - - mega_url, -@@ -108,65 +118,66 @@ impl Mega { - } - - pub fn update_status(&mut self, cx: &mut ModelContext) { -- let checkouts = self.get_checkout_paths(cx); - let config = self.get_fuse_config(cx); -+ let checkouts = self.get_checkout_paths(cx); - - cx.spawn(|this, mut cx| async move { -- if let Ok(opt) = checkouts.await { -+ // When mount point changed, emit an event. -+ // update mount point if it's none. -+ if let Ok(opt) = config.await { - match opt { - None => { - // This means we cannot connect to a localhost port. - // So we can assume that fuse has been dead. -- this.update(&mut cx, |mega, cx| { -+ let _ = this.update(&mut cx, |mega, cx| { - mega.fuse_running = false; - mega.fuse_mounted = false; - cx.emit(Event::FuseRunning(false)); - cx.emit(Event::FuseMounted(None)); -- }) -+ return; -+ }); - } -- Some(info) => { -- // Check if checkout-ed paths are correct -- this.update(&mut cx, |mega, cx| { -- mega.fuse_running = true; -- -- let trie = &mut mega.checkout_path; -- for ref i in info.mounts { -- let missing = trie.get_ancestor(&i.path).is_none(); -- if missing { -- // Should not happen unless on startup. -- trie.insert(i.path.clone(), i.inode); -- cx.emit(Event::FuseCheckout(Some(PathBuf::from( -- i.path.clone(), -- )))) -+ -+ Some(config) => { -+ let _ = this.update(&mut cx, |this, cx| { -+ let path = PathBuf::from(config.config.mount_path); -+ if (this.fuse_mounted && this.fuse_running) && this.mount_point.is_some() { -+ if let Some(inner) = &this.mount_point { -+ if !inner.eq(&path) { -+ this.mount_point = Some(path); -+ cx.emit(Event::FuseMounted(this.mount_point.clone())); -+ } -+ } -+ } else if this.mount_point.is_none() { -+ this.mount_point = Some(path); -+ if this.fuse_running { -+ this.fuse_mounted = true; -+ cx.emit(Event::FuseMounted(this.mount_point.clone())); - } - } -- }) -+ }); - } - } -- } else { -- Ok(()) - } -- .unwrap(); -- -- // When mount point changed, emit an event. -- // update mount point if it's none. -- if let Ok(Some(config)) = config.await { -- this.update(&mut cx, |this, cx| { -- let path = PathBuf::from(config.config.mount_path); -- if (this.fuse_mounted && this.fuse_running) && this.mount_point.is_some() { -- if let Some(inner) = &this.mount_point { -- if !inner.eq(&path) { -- this.mount_point = Some(path); -- cx.emit(Event::FuseMounted(this.mount_point.clone())); -- } -+ -+ if let Ok(Some(info)) = checkouts.await { -+ // Check if checkout-ed paths are correct -+ let _ = this.update(&mut cx, |mega, cx| { -+ mega.fuse_running = true; -+ -+ let trie = &mut mega.checkout_lut; -+ for i in info.mounts.iter() { -+ let path = i.path.parse().unwrap(); -+ -+ let missing = trie.get_ancestor(&path).is_none(); -+ if missing { -+ // Should not happen unless on startup. -+ mega.checkout_path.insert(hash(&path)); -+ trie.insert(path, i.inode); -+ cx.emit(Event::FuseCheckout(Some(PathBuf::from(i.path.clone())))); - } -- } else if this.fuse_running && this.mount_point.is_none() { -- this.mount_point = Some(path); -- cx.emit(Event::FuseMounted(this.mount_point.clone())); - } -- }) -- } else { -- Ok(()) -+ }); - } - }) - .detach(); -@@ -181,7 +192,7 @@ impl Mega { - /// Does nothing if fuse not running. - pub fn toggle_fuse(&mut self, cx: &mut ModelContext) { - self.update_status(cx); -- let paths = &self.checkout_path; -+ let paths = &self.checkout_lut; - - if !self.fuse_running { - return; -@@ -214,7 +225,7 @@ impl Mega { - let path = PathBuf::from(p); // FIXME is there a better way? - cx.spawn(|mega, mut cx| async move { - let recv = mega -- .update(&mut cx, |this, cx| this.restore_path(cx, path)) -+ .update(&mut cx, |this, cx| this.restore_path(cx, &path)) - .expect("mega delegate not be dropped"); - - if let Ok(Some(_resp)) = recv.await { -@@ -284,18 +295,16 @@ impl Mega { - pub fn restore_path( - &self, - cx: &ModelContext, -- path: PathBuf, -+ path: &PathBuf, - ) -> Receiver> { - let (tx, rx) = oneshot::channel(); - let client = self.http_client.clone(); - let uri = format!("{base}/api/fs/umount", base = self.fuse_url); - - // If panics here, that means there's a bug in code. -- // maybe we should ensure every path absolute? -- let path = path.to_str().unwrap(); -- let inode = self.checkout_path.get_ancestor_value(path); -+ let inode = self.checkout_lut.get_ancestor_value(path); - let req = UmountRequest { -- path: Some(path), -+ path: Some(path.to_str().unwrap()), - inode: Some(inode.unwrap().to_owned()), - }; - let body = serde_json::to_string(&req).unwrap(); -@@ -427,29 +436,36 @@ impl Mega { - .detach(); - } - -- pub fn is_path_checkout(&self, path: PathBuf) -> bool { -- let set = &self.checkout_path; -+ pub fn is_path_checkout(&self, path: &PathBuf) -> bool { -+ // FIXME this function calls every time project_panel refresh * entry numbers -+ // the PathBuf construction happens right before calling this -+ // because the trie cannot receive a Arc for finding PathBuf members. -+ // LAG? -+ self.checkout_lut.get_ancestor(path).is_some() -+ } - -- set.get_ancestor(path.to_str().unwrap()).is_some() -+ pub fn is_path_checkout_root(&self, path: &PathBuf) -> bool { -+ self.checkout_path.contains(&hash(path)) - } - -- pub fn mark_checkout(&mut self, cx: &mut ModelContext, path: String, inode: u64) { -- if self.mount_point.is_some() { -- let path = self -- .mount_point -- .clone() -- .unwrap() -- .to_str() -- .unwrap() -- .to_string() -- + path.as_str(); -- self.checkout_path.insert(path, inode); -+ pub fn mark_checkout(&mut self, cx: &mut ModelContext, path: PathBuf, inode: u64) { -+ if let Some(base) = &self.mount_point { -+ self.checkout_path.insert(hash(&path)); -+ self.checkout_lut.insert(path, inode); - cx.emit(Event::FuseCheckout(None)); - } - } - -- pub fn mark_commited(&mut self, cx: &mut ModelContext, path: PathBuf) { -- self.checkout_path.remove(path.to_str().unwrap()); -+ pub fn mark_commited(&mut self, cx: &mut ModelContext, path: &PathBuf) { -+ self.checkout_path.remove(&hash(path)); -+ self.checkout_lut.remove(path); - cx.emit(Event::FuseCheckout(None)); - } -+ -+ pub fn mount_point(&self) -> Option<&PathBuf> { -+ match self.mount_point { -+ Some(ref path) => Some(path), -+ None => None -+ } -+ } - } -diff --git a/crates/mega/src/mega_settings.rs b/crates/mega/src/mega_settings.rs -index bada5ccd80..38916f01fb 100644 ---- a/crates/mega/src/mega_settings.rs -+++ b/crates/mega/src/mega_settings.rs -@@ -1,7 +1,7 @@ --use std::path::PathBuf; --use schemars::JsonSchema; - use gpui::private::serde_derive::{Deserialize, Serialize}; -+use schemars::JsonSchema; - use settings::{Settings, SettingsSources}; -+use std::path::PathBuf; - - #[derive(Default, Deserialize, Debug, Clone, PartialEq)] - pub struct MegaSettings { -@@ -47,4 +47,4 @@ impl Settings for MegaSettings { - ) -> anyhow::Result { - sources.json_merge() - } --} -\ No newline at end of file -+} -diff --git a/crates/mega/src/utils/api.rs b/crates/mega/src/utils/api.rs -index 3251888e60..f96be81187 100644 ---- a/crates/mega/src/utils/api.rs -+++ b/crates/mega/src/utils/api.rs -@@ -1,7 +1,7 @@ - use serde::{Deserialize, Serialize}; - --const SUCCESS: &str = "Success"; --const FAIL : &str = "Fail"; -+const SUCCESS: &str = "Success"; -+const FAIL: &str = "Fail"; - #[derive(Debug, Deserialize, Serialize)] - pub struct MountRequest<'a> { - pub path: &'a str, -@@ -102,4 +102,4 @@ impl FuseResponse for ConfigResponse { - fn is_resp_failed(&self) -> bool { - self.status.eq(FAIL) - } --} -\ No newline at end of file -+} -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index c5105988e0..c31a341b84 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -7,8 +7,8 @@ use gpui::private::serde_json; - use gpui::{ - actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, - EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, -- ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, Styled, Task -- , View, ViewContext, VisualContext, WeakView, WindowContext, -+ ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, Styled, Task, View, -+ ViewContext, VisualContext, WeakView, WindowContext, - }; - use mega::Mega; - use settings::Settings; -@@ -273,14 +273,25 @@ impl MegaPanel { - } - - v_flex().id("mega-control-pad").size_full().children([ -+ encap_btn( -+ Button::new("refresh_mega_status", "Refresh Status") -+ .full_width() -+ .icon(IconName::Control) -+ .icon_position(IconPosition::Start) -+ .on_click(cx.listener(|this, _, cx | { -+ this.mega_handle.update(cx, |mega, cx| { -+ mega.update_status(cx); -+ println!("{mega:?}"); -+ }) -+ })) -+ ), - encap_btn( - Button::new("btn_toggle_mount", "Toggle Fuse Running") - .full_width() - .icon(IconName::Context) - .icon_position(IconPosition::Start) - .on_click(cx.listener(|this, _, cx| { -- this.mega_handle -- .update(cx, |mega, cx| mega.toggle_mount(cx)); -+ this.mega_handle.update(cx, |mega, cx| mega.toggle_mount(cx)); - })), - ), - encap_btn( -diff --git a/crates/mega_panel/src/mega_panel_settings.rs b/crates/mega_panel/src/mega_panel_settings.rs -index bfd4b337d0..60c8229f77 100644 ---- a/crates/mega_panel/src/mega_panel_settings.rs -+++ b/crates/mega_panel/src/mega_panel_settings.rs -@@ -1,6 +1,6 @@ --use schemars::JsonSchema; --use gpui::Pixels; - use gpui::private::serde::{Deserialize, Serialize}; -+use gpui::Pixels; -+use schemars::JsonSchema; - use settings::{Settings, SettingsSources}; - - #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Copy, PartialEq)] -@@ -44,4 +44,4 @@ impl Settings for MegaPanelSettings { - ) -> anyhow::Result { - sources.json_merge() - } --} -\ No newline at end of file -+} -diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs -index 70ad294cd9..fcf0e733b1 100644 ---- a/crates/project_panel/src/project_panel.rs -+++ b/crates/project_panel/src/project_panel.rs -@@ -26,7 +26,8 @@ use gpui::{ - WindowContext, - }; - use indexmap::IndexMap; --use mega::{api::FuseResponse, Mega}; -+use mega::utils::api::FuseResponse; -+use mega::Mega; - use menu::{Confirm, SelectFirst, SelectLast, SelectNext, SelectPrev}; - use project::{ - relativize_path, Entry, EntryKind, Fs, Project, ProjectEntryId, ProjectPath, Worktree, -@@ -44,6 +45,7 @@ use std::{ - sync::Arc, - time::Duration, - }; -+use std::ops::Deref; - use theme::ThemeSettings; - use ui::{prelude::*, v_flex, ContextMenu, Icon, Label, ListItem, Tooltip}; - use util::{maybe, ResultExt, TryFutureExt}; -@@ -114,6 +116,8 @@ struct EntryDetails { - path: Arc, - depth: usize, - kind: EntryKind, -+ is_checkout: bool, -+ is_checkout_root: bool, - is_ignored: bool, - is_expanded: bool, - is_selected: bool, -@@ -530,8 +534,8 @@ impl ProjectPanel { - entry_id, - }); - -- // FIXME add fuse dir specific behaviors - if let Some((worktree, entry)) = self.selected_sub_entry(cx) { -+ let pb: PathBuf = entry.path.to_path_buf(); - let auto_fold_dirs = ProjectPanelSettings::get_global(cx).auto_fold_dirs; - let is_root = Some(entry) == worktree.root_entry(); - let is_dir = entry.is_dir(); -@@ -541,7 +545,8 @@ impl ProjectPanel { - let is_read_only = project.is_read_only(cx); - let is_remote = project.is_via_collab() && project.dev_server_project_id().is_none(); - let is_local = project.is_local(); -- let is_checkout = mega.is_path_checkout(entry.path.to_path_buf()); -+ let is_checkout = mega.is_path_checkout(&pb); -+ let is_checkout_root = mega.is_path_checkout_root(&pb); - - let context_menu = ContextMenu::build(cx, |menu, cx| { - menu.context(self.focus_handle.clone()).map(|menu| { -@@ -553,9 +558,11 @@ impl ProjectPanel { - menu.when(!is_checkout && !is_root, |menu| { - menu.action("Checkout Path", Box::new(CheckoutPath)) - }) -- .when(is_checkout, |menu| { -+ .when(is_checkout && is_checkout_root, |menu| { - menu.action("Commit Path", Box::new(CommitPath)) -- .separator() -+ }) -+ .when(is_checkout && !is_checkout_root, |menu| { -+ menu.separator() - .action("New File", Box::new(NewFile)) - .action("New Folder", Box::new(NewDirectory)) - .separator() -@@ -604,20 +611,19 @@ impl ProjectPanel { - // .action("Rename", Box::new(Rename)) - }) - .when(!is_remote & is_root, |menu| { -- menu -- .action( -- "Add Folder to Project…", -- Box::new(workspace::AddFolderToProject), -- ) -- .entry( -- "Remove from Project", -- None, -- cx.handler_for(&this, move |this, cx| { -- this.project.update(cx, |project, cx| { -- project.remove_worktree(worktree_id, cx) -- }); -- }), -- ) -+ menu.action( -+ "Add Folder to Project…", -+ Box::new(workspace::AddFolderToProject), -+ ) -+ .entry( -+ "Remove from Project", -+ None, -+ cx.handler_for(&this, move |this, cx| { -+ this.project.update(cx, |project, cx| { -+ project.remove_worktree(worktree_id, cx) -+ }); -+ }), -+ ) - }) - .when(is_root, |menu| { - menu.separator() -@@ -1344,16 +1350,18 @@ impl ProjectPanel { - - fn checkout_specific_path(&mut self, _: &CheckoutPath, cx: &mut ViewContext) { - if let Some((_, entry)) = self.selected_entry_handle(cx) { -- let path = entry.path.clone(); -+ let path = entry.path.to_path_buf(); - self.mega.update(cx, |mega, cx| { -- let recv = mega.checkout_path(cx, path.to_path_buf()); -+ println!("Checkout: {:?}", path); -+ let recv = mega.checkout_path(cx, path); - cx.spawn(|this, mut cx| async move { - let resp = recv.await; - println!("Response: {resp:?}"); - if let Ok(Some(resp)) = resp { - if resp.is_resp_succeed() { - this.update(&mut cx, |mega, cx| { -- mega.mark_checkout(cx, resp.mount.path, resp.mount.inode); -+ let path = resp.mount.path.parse().unwrap(); -+ mega.mark_checkout(cx, path, resp.mount.inode); - }) - .expect("Mega delegate not been dropped"); - } -@@ -1365,17 +1373,18 @@ impl ProjectPanel { - } - - fn commit_specific_path(&mut self, _: &CommitPath, cx: &mut ViewContext) { -+ // TODO close windows that are in the commited paths. - if let Some((_, entry)) = self.selected_entry_handle(cx) { -- let path = entry.path.clone(); -+ let path = entry.path.to_path_buf(); - self.mega.update(cx, |mega, cx| { -- let recv = mega.restore_path(cx, path.to_path_buf()); -+ let recv = mega.restore_path(cx, &path); - cx.spawn(|this, mut cx| async move { - let resp = recv.await; - println!("Response: {resp:?}"); - if let Ok(Some(resp)) = resp { - if resp.is_resp_succeed() { - this.update(&mut cx, |mega, cx| { -- mega.mark_commited(cx, path.to_path_buf()); -+ mega.mark_commited(cx, &path); - }) - .expect("Mega delegate not been dropped"); - } -@@ -2302,12 +2311,18 @@ impl ProjectPanel { - worktree_id: snapshot.id(), - entry_id: entry.id, - }; -+ -+ let pb = entry.path.to_path_buf(); -+ let is_checkout = self.mega.read(cx).is_path_checkout(&pb); -+ let is_checkout_root = self.mega.read(cx).is_path_checkout_root(&pb); - let mut details = EntryDetails { - filename, - icon, - path: entry.path.clone(), - depth, - kind: entry.kind, -+ is_checkout, -+ is_checkout_root, - is_ignored: entry.is_ignored, - is_expanded, - is_selected: self.selection == Some(selection), --- -2.43.0 - diff --git a/scripts/zed-intergration/patches/0023-display-checkout-points-in-mega_panel.patch b/scripts/zed-intergration/patches/0023-display-checkout-points-in-mega_panel.patch deleted file mode 100644 index ab75add38..000000000 --- a/scripts/zed-intergration/patches/0023-display-checkout-points-in-mega_panel.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 3bdfb29034ba58d16539c2cb2f9cfeb636abd5ff Mon Sep 17 00:00:00 2001 -From: Neon -Date: Tue, 19 Nov 2024 20:19:53 +0800 -Subject: [PATCH 23/24] display checkout points in mega_panel - ---- - crates/mega/src/mega.rs | 27 ++++++++++++++++++++------- - crates/mega_panel/src/mega_panel.rs | 21 +++++++++++++++------ - 2 files changed, 35 insertions(+), 13 deletions(-) - -diff --git a/crates/mega/src/mega.rs b/crates/mega/src/mega.rs -index 628fe311d9..c9473097ee 100644 ---- a/crates/mega/src/mega.rs -+++ b/crates/mega/src/mega.rs -@@ -62,8 +62,12 @@ impl EventEmitter for Mega {} - - impl Debug for Mega { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { -- let lut = self.checkout_lut.keys().map(|key| key.to_path_buf()).collect::>(); -- -+ let lut = self -+ .checkout_lut -+ .keys() -+ .map(|key| key.to_path_buf()) -+ .collect::>(); -+ - write!( - f, - "fuse_executable: {:?}, mega_url: {}, fuse_url: {}\n\ -@@ -99,7 +103,7 @@ impl Mega { - log::error!("Mount point in setting does not exist"); - None - }; -- -+ - Mega { - fuse_executable, - -@@ -141,7 +145,9 @@ impl Mega { - Some(config) => { - let _ = this.update(&mut cx, |this, cx| { - let path = PathBuf::from(config.config.mount_path); -- if (this.fuse_mounted && this.fuse_running) && this.mount_point.is_some() { -+ if (this.fuse_mounted && this.fuse_running) -+ && this.mount_point.is_some() -+ { - if let Some(inner) = &this.mount_point { - if !inner.eq(&path) { - this.mount_point = Some(path); -@@ -159,7 +165,7 @@ impl Mega { - } - } - } -- -+ - if let Ok(Some(info)) = checkouts.await { - // Check if checkout-ed paths are correct - let _ = this.update(&mut cx, |mega, cx| { -@@ -187,6 +193,13 @@ impl Mega { - (self.fuse_running, self.fuse_mounted) - } - -+ pub fn checkout_points(&self) -> Vec { -+ self.checkout_lut -+ .keys() -+ .map(|key| key.as_path().to_str().unwrap().to_string()) -+ .collect() -+ } -+ - /// ## Toggle Fuse checkouts - /// Checkout or un-checkout the paths in zed. - /// Does nothing if fuse not running. -@@ -461,11 +474,11 @@ impl Mega { - self.checkout_lut.remove(path); - cx.emit(Event::FuseCheckout(None)); - } -- -+ - pub fn mount_point(&self) -> Option<&PathBuf> { - match self.mount_point { - Some(ref path) => Some(path), -- None => None -+ None => None, - } - } - } -diff --git a/crates/mega_panel/src/mega_panel.rs b/crates/mega_panel/src/mega_panel.rs -index c31a341b84..69e42259b6 100644 ---- a/crates/mega_panel/src/mega_panel.rs -+++ b/crates/mega_panel/src/mega_panel.rs -@@ -4,12 +4,7 @@ use db::kvp::KEY_VALUE_STORE; - use fs::Fs; - use gpui::private::serde_derive::{Deserialize, Serialize}; - use gpui::private::serde_json; --use gpui::{ -- actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, ElementId, -- EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, -- ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, Styled, Task, View, -- ViewContext, VisualContext, WeakView, WindowContext, --}; -+use gpui::{actions, div, Action, AppContext, AssetSource, AsyncWindowContext, Div, Element, ElementId, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement, Pixels, PromptLevel, Render, SharedString, Stateful, Styled, Task, View, ViewContext, VisualContext, WeakView, WindowContext}; - use mega::Mega; - use settings::Settings; - use std::sync::Arc; -@@ -98,6 +93,8 @@ impl Render for MegaPanel { - .child(horizontal_separator(cx)) - .child(self.render_status(cx)) - .child(horizontal_separator(cx)) -+ .child(self.render_checkout_points(cx)) -+ .child(horizontal_separator(cx)) - .child(self.render_buttons(cx)); - - mega_panel -@@ -267,6 +264,18 @@ impl MegaPanel { - ]) - } - -+ fn render_checkout_points(&mut self, cx: &mut ViewContext) -> Stateful
{ -+ let points = self.mega_handle.read(cx).checkout_points(); -+ let points: Vec