From 9da1cc48755023d45114185dcafd7d8175be919b Mon Sep 17 00:00:00 2001 From: Neon Date: Tue, 12 Nov 2024 19:19:45 +0800 Subject: [PATCH] zed integration: buggy but work --- scripts/zed-intergration/.gitignore | 2 +- ...1-add-new-module-mega-and-mega_panel.patch | 2 +- ...-integrate-basic-panel-code-with-zed.patch | 2 +- ...-add-mega-panel-trait-implementation.patch | 2 +- .../0004-fix-make-mega_panel-runnable.patch | 2 +- ...panel-very-basic-info-render-support.patch | 2 +- .../0006-mega-basic-rest-api-support.patch | 2 +- ...-control-pad-and-information-display.patch | 2 +- .../0008-mega-feat-toggle-fuse-mount.patch | 2 +- ...-Fix-dont-restore-previous-workspace.patch | 2 +- .../0010-Fix-checkout-in-project_panel.patch | 2 +- ...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 +++++ 15 files changed, 1699 insertions(+), 11 deletions(-) create mode 100644 scripts/zed-intergration/patches/0011-Add-basic-mega-rest-api-support.patch create mode 100644 scripts/zed-intergration/patches/0012-fix-api-call-logic.patch create mode 100644 scripts/zed-intergration/patches/0013-fix-features-wrongly-opened.patch create mode 100644 scripts/zed-intergration/patches/0014-fix-checkout-in-context-menu.patch diff --git a/scripts/zed-intergration/.gitignore b/scripts/zed-intergration/.gitignore index 1d81e29f..18d40299 100644 --- a/scripts/zed-intergration/.gitignore +++ b/scripts/zed-intergration/.gitignore @@ -1 +1 @@ -zed/ +/zed/ 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 index 24cba31b..94b62ca3 100644 --- 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 @@ -1,7 +1,7 @@ From 006bd0e01b5deba6792af824a5a73c32e96efa2c Mon Sep 17 00:00:00 2001 From: Neon Date: Sat, 19 Oct 2024 21:24:00 +0800 -Subject: [PATCH 01/10] add new module mega and mega_panel +Subject: [PATCH 01/14] add new module mega and mega_panel --- Cargo.lock | 23 ++++++ 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 index a3990194..555228fb 100644 --- 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 @@ -1,7 +1,7 @@ From afca3aee776df6674d0c6d17858d944c64ec56ae Mon Sep 17 00:00:00 2001 From: Neon Date: Mon, 21 Oct 2024 09:18:40 +0800 -Subject: [PATCH 02/10] mega: integrate basic panel code with zed +Subject: [PATCH 02/14] mega: integrate basic panel code with zed --- Cargo.lock | 7 +- 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 index e0aeca8b..6ce1cbb1 100644 --- a/scripts/zed-intergration/patches/0003-add-mega-panel-trait-implementation.patch +++ b/scripts/zed-intergration/patches/0003-add-mega-panel-trait-implementation.patch @@ -1,7 +1,7 @@ From a6636b00e11cfa284e2e152cb2ac0a6d92508a34 Mon Sep 17 00:00:00 2001 From: Neon Date: Mon, 21 Oct 2024 09:33:24 +0800 -Subject: [PATCH 03/10] add: mega `panel` trait implementation +Subject: [PATCH 03/14] add: mega `panel` trait implementation --- Cargo.lock | 1 + 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 index f743cc1d..ad372760 100644 --- a/scripts/zed-intergration/patches/0004-fix-make-mega_panel-runnable.patch +++ b/scripts/zed-intergration/patches/0004-fix-make-mega_panel-runnable.patch @@ -1,7 +1,7 @@ From 5e676b9b1669d078a25bcee9a0d1b87743862a30 Mon Sep 17 00:00:00 2001 From: Neon Date: Mon, 21 Oct 2024 10:00:36 +0800 -Subject: [PATCH 04/10] fix: make mega_panel runnable +Subject: [PATCH 04/14] fix: make mega_panel runnable --- assets/settings/default.json | 8 ++++++++ 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 index 5bea9ecc..0980ab50 100644 --- 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 @@ -1,7 +1,7 @@ From e04d4b01af7991ed4b40fcd9553f20e67f2ec53f Mon Sep 17 00:00:00 2001 From: Neon Date: Tue, 22 Oct 2024 16:15:01 +0800 -Subject: [PATCH 05/10] mega_panel: very basic info render support +Subject: [PATCH 05/14] mega_panel: very basic info render support --- Cargo.lock | 4 +- 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 index da1f1f21..6d6cca42 100644 --- a/scripts/zed-intergration/patches/0006-mega-basic-rest-api-support.patch +++ b/scripts/zed-intergration/patches/0006-mega-basic-rest-api-support.patch @@ -1,7 +1,7 @@ From 8b57a9f693c95e92ee5299ff30b6cd791c08da71 Mon Sep 17 00:00:00 2001 From: Neon Date: Tue, 22 Oct 2024 19:12:08 +0800 -Subject: [PATCH 06/10] mega: basic rest api support +Subject: [PATCH 06/14] mega: basic rest api support --- Cargo.lock | 1 + 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 index 963b15cd..caf27d49 100644 --- 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 @@ -1,7 +1,7 @@ From 0ae6bfb40025aca376878982579a322eaa231143 Mon Sep 17 00:00:00 2001 From: Neon Date: Sat, 26 Oct 2024 22:02:19 +0800 -Subject: [PATCH 07/10] mega_panel: control pad and information display +Subject: [PATCH 07/14] mega_panel: control pad and information display --- crates/mega/src/mega.rs | 56 ++++++++--- 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 index 9e3a072a..e7823b52 100644 --- a/scripts/zed-intergration/patches/0008-mega-feat-toggle-fuse-mount.patch +++ b/scripts/zed-intergration/patches/0008-mega-feat-toggle-fuse-mount.patch @@ -1,7 +1,7 @@ From 8f8d3a30a45fa4f3b2359060d63a51f065c327d9 Mon Sep 17 00:00:00 2001 From: Neon Date: Tue, 29 Oct 2024 18:50:39 +0800 -Subject: [PATCH 08/10] mega: feat toggle fuse mount +Subject: [PATCH 08/14] mega: feat toggle fuse mount --- Cargo.lock | 6 +- 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 index 81b5ddfb..81893938 100644 --- a/scripts/zed-intergration/patches/0009-Fix-dont-restore-previous-workspace.patch +++ b/scripts/zed-intergration/patches/0009-Fix-dont-restore-previous-workspace.patch @@ -1,7 +1,7 @@ From 69f92bb2dbb1b2facf7b60cb6c6e1c0d211c4f4d Mon Sep 17 00:00:00 2001 From: Neon Date: Tue, 29 Oct 2024 21:08:56 +0800 -Subject: [PATCH 09/10] Fix: dont restore previous workspace +Subject: [PATCH 09/14] Fix: dont restore previous workspace --- crates/project/src/project.rs | 106 ++++++++++++++++++++++ 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 index 5498ebc3..f23549b6 100644 --- a/scripts/zed-intergration/patches/0010-Fix-checkout-in-project_panel.patch +++ b/scripts/zed-intergration/patches/0010-Fix-checkout-in-project_panel.patch @@ -1,7 +1,7 @@ From f2551513e804e8f43f6fac39d58befffd9dcda39 Mon Sep 17 00:00:00 2001 From: Neon Date: Wed, 30 Oct 2024 10:53:59 +0800 -Subject: [PATCH 10/10] Fix checkout in project_panel +Subject: [PATCH 10/14] Fix checkout in project_panel --- crates/mega/src/mega.rs | 18 +++++++++- 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 new file mode 100644 index 00000000..053b6ffd --- /dev/null +++ b/scripts/zed-intergration/patches/0011-Add-basic-mega-rest-api-support.patch @@ -0,0 +1,835 @@ +From a880b2c68d47990c8229656313b9dbeb1000b87c Mon Sep 17 00:00:00 2001 +From: Neon +Date: Sun, 10 Nov 2024 22:19:15 +0800 +Subject: [PATCH 11/14] 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 new file mode 100644 index 00000000..0e6c3db5 --- /dev/null +++ b/scripts/zed-intergration/patches/0012-fix-api-call-logic.patch @@ -0,0 +1,611 @@ +From 3c45fed1fd917dac0051917d7d9685371f35cd60 Mon Sep 17 00:00:00 2001 +From: Neon +Date: Tue, 12 Nov 2024 16:56:00 +0800 +Subject: [PATCH 12/14] 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 new file mode 100644 index 00000000..40c70de0 --- /dev/null +++ b/scripts/zed-intergration/patches/0013-fix-features-wrongly-opened.patch @@ -0,0 +1,35 @@ +From 42916a9fae734c3a0b3dcc8d90f77669378a20c2 Mon Sep 17 00:00:00 2001 +From: Neon +Date: Tue, 12 Nov 2024 17:55:27 +0800 +Subject: [PATCH 13/14] 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 new file mode 100644 index 00000000..c6d81c94 --- /dev/null +++ b/scripts/zed-intergration/patches/0014-fix-checkout-in-context-menu.patch @@ -0,0 +1,207 @@ +From 14806e63bfc717cd17f933fb1aecd6cded410497 Mon Sep 17 00:00:00 2001 +From: Neon +Date: Tue, 12 Nov 2024 19:12:29 +0800 +Subject: [PATCH 14/14] 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 +