From 11d758ea1f879bb8bb014b0478fbd1a8bb2b1a1d Mon Sep 17 00:00:00 2001 From: "benjamin.747" Date: Fri, 9 Aug 2024 17:47:09 +0800 Subject: [PATCH] running mega as sidecar in tauri app and update config --- Cargo.toml | 21 +++-- ceres/src/model/create_file.rs | 21 ----- gateway/Cargo.toml | 1 + gateway/src/https_server.rs | 75 ++++++++--------- jupiter/Cargo.toml | 1 - jupiter/src/storage/git_db_storage.rs | 93 ++++++++++++-------- jupiter/src/storage/mega_storage.rs | 107 +++++++++++++----------- lunar/src-tauri/.gitignore | 2 + lunar/src-tauri/Cargo.toml | 6 +- lunar/src-tauri/build.rs | 58 +++++++++++++ lunar/src-tauri/src/main.rs | 59 ++++++++++--- lunar/src-tauri/tauri.conf.json | 21 +++-- lunar/src-tauri/tauri.linux.conf.json | 9 ++ lunar/src-tauri/tauri.macos.conf.json | 9 ++ lunar/src-tauri/tauri.windows.conf.json | 9 ++ lunar/src/app/application-layout.tsx | 2 +- lunar/src/app/settings/page.tsx | 27 ++---- mega/Cargo.toml | 1 - venus/src/monorepo/mega_node.rs | 95 --------------------- venus/src/monorepo/mod.rs | 3 +- 20 files changed, 323 insertions(+), 297 deletions(-) create mode 100644 lunar/src-tauri/tauri.linux.conf.json create mode 100644 lunar/src-tauri/tauri.macos.conf.json create mode 100644 lunar/src-tauri/tauri.windows.conf.json delete mode 100644 venus/src/monorepo/mega_node.rs diff --git a/Cargo.toml b/Cargo.toml index 9de04213d..9fb4a3965 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ members = [ "lunar/src-tauri", "atlas", ] -default-members = ["mega", "libra","aries"] +default-members = ["mega", "libra", "aries"] exclude = ["craft"] resolver = "1" @@ -35,23 +35,22 @@ saturn = { path = "saturn" } taurus = { path = "taurus" } mega = { path = "mega" } anyhow = "1.0.86" -serde = {version = "1.0.203", features = ["derive"]} -serde_json = "1.0.117" +serde = "1.0.205" +serde_json = "1.0.122" tracing = "0.1.40" tracing-subscriber = "0.3.18" tracing-appender = "0.2" -thiserror = "1.0.61" +thiserror = "1.0.63" rand = "0.8.5" smallvec = "1.13.2" -tokio = "1.38.0" +tokio = "1.39.2" tokio-stream = "0.1.15" tokio-test = "0.4.4" -rayon = "1.10.0" -clap = "4.5.4" -async-trait = "0.1.80" +clap = "4.5.14" +async-trait = "0.1.81" async-stream = "0.3.5" -bytes = "1.6.0" -memchr = "2.7.2" +bytes = "1.7.1" +memchr = "2.7.4" chrono = "0.4.38" sha1 = "0.10.6" sha256 = "1.5" @@ -67,7 +66,7 @@ tower = "0.4.13" hex = "0.4.3" sea-orm = "1.0.0" flate2 = "1.0.30" -bstr = "1.9.1" +bstr = "1.10.0" colored = "2.1.0" idgenerator = "2.0.0" num_cpus = "1.16.0" diff --git a/ceres/src/model/create_file.rs b/ceres/src/model/create_file.rs index 092bb6ce4..dc793f070 100644 --- a/ceres/src/model/create_file.rs +++ b/ceres/src/model/create_file.rs @@ -1,11 +1,5 @@ -use std::cell::RefCell; - use serde::{Deserialize, Serialize}; -use mercury::{hash::SHA1, internal::object::tree::TreeItemMode}; - -use venus::monorepo::mega_node::MegaNode; - #[derive(PartialEq, Eq, Debug, Clone, Default, Serialize, Deserialize)] pub struct CreateFileInfo { /// can be a file or directory @@ -16,18 +10,3 @@ pub struct CreateFileInfo { // pub import_dir: bool, pub content: Option, } - - -impl From for MegaNode { - fn from(value: CreateFileInfo) -> Self { - MegaNode { - name: value.name, - path: value.path.parse().unwrap(), - is_directory: value.is_directory, - children: RefCell::new(vec![]), - id: SHA1::default(), - mode: TreeItemMode::Tree, - commit_id: SHA1::default(), - } - } -} diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index 8ebf9c7b7..8844af454 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -46,3 +46,4 @@ reqwest = { workspace = true, features = ["json"] } uuid = { workspace = true, features = ["v4"] } regex = "1.10.4" ed25519-dalek = { version = "2.1.1", features = ["pkcs8"] } +lazy_static ={ workspace = true } diff --git a/gateway/src/https_server.rs b/gateway/src/https_server.rs index adaaba025..ba851028c 100644 --- a/gateway/src/https_server.rs +++ b/gateway/src/https_server.rs @@ -15,6 +15,7 @@ use axum::routing::get; use axum::Router; use axum_server::tls_rustls::RustlsConfig; use clap::Args; +use lazy_static::lazy_static; use regex::Regex; use tokio::sync::Mutex; use tower::ServiceBuilder; @@ -160,6 +161,7 @@ pub async fn app(config: Config, host: String, port: u16, common: CommonOptions) sessions: Arc::new(Mutex::new(HashMap::new())), }), ) + // Using Regular Expressions for Path Matching in Protocol .route( "/*path", get(get_method_router) @@ -177,6 +179,20 @@ pub async fn app(config: Config, host: String, port: u16, common: CommonOptions) .with_state(state) } +lazy_static! { + //GET + static ref OBJECTS_REGEX: Regex = Regex::new(r"/objects/[a-z0-9]+$").unwrap(); + static ref LOCKS_REGEX: Regex = Regex::new(r"/locks$").unwrap(); + static ref INFO_REFS_REGEX: Regex = Regex::new(r"/info/refs$").unwrap(); + //POST + static ref REGEX_LOCKS_VERIFY: Regex = Regex::new(r"/locks/verify$").unwrap(); + static ref REGEX_UNLOCK: Regex = Regex::new(r"/unlock$").unwrap(); + static ref REGEX_OBJECTS_BATCH: Regex = Regex::new(r"/objects/batch$").unwrap(); + static ref REGEX_OBJECTS_CHUNKIDS: Regex = Regex::new(r"objects/chunkids$").unwrap(); + static ref REGEX_GIT_UPLOAD_PACK: Regex = Regex::new(r"/git-upload-pack$").unwrap(); + static ref REGEX_GIT_RECEIVE_PACK: Regex = Regex::new(r"/git-receive-pack$").unwrap(); +} + async fn get_method_router( state: State, Query(params): Query, @@ -184,25 +200,22 @@ async fn get_method_router( ) -> Result, (StatusCode, String)> { let lfs_config: LfsConfig = state.deref().to_owned().into(); // Routing LFS services. - if Regex::new(r"/objects/[a-z0-9]+$") - .unwrap() - .is_match(uri.path()) - { + if OBJECTS_REGEX.is_match(uri.path()) { lfs::lfs_download_object(&lfs_config, uri.path()).await - } else if Regex::new(r"/locks$").unwrap().is_match(uri.path()) { - return lfs::lfs_retrieve_lock(&lfs_config, params).await; - } else if Regex::new(r"/info/refs$").unwrap().is_match(uri.path()) { + } else if LOCKS_REGEX.is_match(uri.path()) { + lfs::lfs_retrieve_lock(&lfs_config, params).await + } else if INFO_REFS_REGEX.is_match(uri.path()) { let pack_protocol = SmartProtocol::new( remove_git_suffix(uri, "/info/refs"), state.context.clone(), TransportProtocol::Http, ); - return crate::git_protocol::http::git_info_refs(params, pack_protocol).await; + crate::git_protocol::http::git_info_refs(params, pack_protocol).await } else { - return Err(( + Err(( StatusCode::NOT_FOUND, String::from("Operation not supported\n"), - )); + )) } } @@ -213,38 +226,27 @@ async fn post_method_router( ) -> Result { let lfs_config: LfsConfig = state.deref().to_owned().into(); // Routing LFS services. - if Regex::new(r"/locks/verify$").unwrap().is_match(uri.path()) { + if REGEX_LOCKS_VERIFY.is_match(uri.path()) { lfs::lfs_verify_lock(state, &lfs_config, req).await - } else if Regex::new(r"/locks$").unwrap().is_match(uri.path()) { - return lfs::lfs_create_lock(state, &lfs_config, req).await; - } else if Regex::new(r"/unlock$").unwrap().is_match(uri.path()) { - return lfs::lfs_delete_lock(state, &lfs_config, uri.path(), req).await; - } else if Regex::new(r"/objects/batch$").unwrap().is_match(uri.path()) { - return lfs::lfs_process_batch(state, &lfs_config, req).await; - } else if Regex::new(r"objects/chunkids$") - .unwrap() - .is_match(uri.path()) - { - return lfs::lfs_fetch_chunk_ids(state, &lfs_config, req).await; - } - // Routing git services. - else if Regex::new(r"/git-upload-pack$") - .unwrap() - .is_match(uri.path()) - { + } else if LOCKS_REGEX.is_match(uri.path()) { + lfs::lfs_create_lock(state, &lfs_config, req).await + } else if REGEX_UNLOCK.is_match(uri.path()) { + lfs::lfs_delete_lock(state, &lfs_config, uri.path(), req).await + } else if REGEX_OBJECTS_BATCH.is_match(uri.path()) { + lfs::lfs_process_batch(state, &lfs_config, req).await + } else if REGEX_OBJECTS_CHUNKIDS.is_match(uri.path()) { + lfs::lfs_fetch_chunk_ids(state, &lfs_config, req).await + } else if REGEX_GIT_UPLOAD_PACK.is_match(uri.path()) { let mut pack_protocol = SmartProtocol::new( - remove_git_suffix(uri, "/git-upload-pack"), + remove_git_suffix(uri.clone(), "/git-upload-pack"), state.context.clone(), TransportProtocol::Http, ); pack_protocol.service_type = Some(ServiceType::UploadPack); crate::git_protocol::http::git_upload_pack(req, pack_protocol).await - } else if Regex::new(r"/git-receive-pack$") - .unwrap() - .is_match(uri.path()) - { + } else if REGEX_GIT_RECEIVE_PACK.is_match(uri.path()) { let mut pack_protocol = SmartProtocol::new( - remove_git_suffix(uri, "/git-receive-pack"), + remove_git_suffix(uri.clone(), "/git-receive-pack"), state.context.clone(), TransportProtocol::Http, ); @@ -264,10 +266,7 @@ async fn put_method_router( req: Request, ) -> Result, (StatusCode, String)> { let lfs_config: LfsConfig = state.deref().to_owned().into(); - if Regex::new(r"/objects/[a-z0-9]+$") - .unwrap() - .is_match(uri.path()) - { + if OBJECTS_REGEX.is_match(uri.path()) { lfs::lfs_upload_object(&lfs_config, uri.path(), req).await } else { Err(( diff --git a/jupiter/Cargo.toml b/jupiter/Cargo.toml index 3449a4bf9..03e137cbe 100644 --- a/jupiter/Cargo.toml +++ b/jupiter/Cargo.toml @@ -29,7 +29,6 @@ async-trait = { workspace = true } futures = { workspace = true } serde_json = { workspace = true } idgenerator = { workspace = true } -rayon = { workspace = true } handlebars = "6.0.0" [dev-dependencies] diff --git a/jupiter/src/storage/git_db_storage.rs b/jupiter/src/storage/git_db_storage.rs index 08e9e639b..3805789bb 100644 --- a/jupiter/src/storage/git_db_storage.rs +++ b/jupiter/src/storage/git_db_storage.rs @@ -1,8 +1,7 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; -use futures::Stream; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use futures::{stream, Stream, StreamExt}; use sea_orm::sea_query::Expr; use sea_orm::{ ActiveModelTrait, ColumnTrait, DatabaseConnection, DbBackend, DbErr, EntityTrait, @@ -33,6 +32,15 @@ pub struct GitDbStorage { pub raw_obj_threshold: usize, } +#[derive(Debug)] +struct GitObjects { + pub commits: Vec, + trees: Vec, + blobs: Vec, + raw_blobs: Vec, + tags: Vec, +} + #[async_trait] impl GitStorageProvider for GitDbStorage { async fn save_ref(&self, repo: &Repo, refs: &RefCommand) -> Result<(), MegaError> { @@ -127,50 +135,63 @@ impl GitDbStorage { } pub async fn save_entry(&self, repo: &Repo, entry_list: Vec) -> Result<(), MegaError> { - let (commits, trees, blobs, raw_blobs, tags) = ( - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - ); - entry_list.par_iter().for_each(|entry| { - let raw_obj = entry.process_entry(); - let model = raw_obj.convert_to_git_model(); - match model { - GitObjectModel::Commit(mut commit) => { - commit.repo_id = repo.repo_id; - commits.lock().unwrap().push(commit.into_active_model()) - } - GitObjectModel::Tree(mut tree) => { - tree.repo_id = repo.repo_id; - trees.lock().unwrap().push(tree.clone().into_active_model()); + let git_objects = Arc::new(Mutex::new(GitObjects { + commits: Vec::new(), + trees: Vec::new(), + blobs: Vec::new(), + raw_blobs: Vec::new(), + tags: Vec::new(), + })); + + stream::iter(entry_list) + .for_each_concurrent(None, |entry| { + let git_objects = git_objects.clone(); + + async move { + let raw_obj = entry.process_entry(); + let model = raw_obj.convert_to_git_model(); + let mut git_objects = git_objects.lock().unwrap(); + + match model { + GitObjectModel::Commit(mut commit) => { + commit.repo_id = repo.repo_id; + git_objects.commits.push(commit.into_active_model()) + } + GitObjectModel::Tree(mut tree) => { + tree.repo_id = repo.repo_id; + git_objects.trees.push(tree.clone().into_active_model()); + } + GitObjectModel::Blob(mut blob, raw) => { + blob.repo_id = repo.repo_id; + git_objects.blobs.push(blob.clone().into_active_model()); + git_objects.raw_blobs.push(raw.into_active_model()); + } + GitObjectModel::Tag(mut tag) => { + tag.repo_id = repo.repo_id; + git_objects.tags.push(tag.into_active_model()) + } + } } - GitObjectModel::Blob(mut blob, raw) => { - blob.repo_id = repo.repo_id; - blobs.lock().unwrap().push(blob.clone().into_active_model()); - raw_blobs.lock().unwrap().push(raw.into_active_model()); - } - GitObjectModel::Tag(mut tag) => { - tag.repo_id = repo.repo_id; - tags.lock().unwrap().push(tag.into_active_model()) - } - } - }); + }) + .await; - batch_save_model(self.get_connection(), commits.into_inner().unwrap()) + let git_objects = Arc::try_unwrap(git_objects) + .expect("Failed to unwrap Arc") + .into_inner() + .unwrap(); + batch_save_model(self.get_connection(), git_objects.commits) .await .unwrap(); - batch_save_model(self.get_connection(), trees.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.trees) .await .unwrap(); - batch_save_model(self.get_connection(), blobs.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.blobs) .await .unwrap(); - batch_save_model(self.get_connection(), raw_blobs.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.raw_blobs) .await .unwrap(); - batch_save_model(self.get_connection(), tags.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.tags) .await .unwrap(); Ok(()) diff --git a/jupiter/src/storage/mega_storage.rs b/jupiter/src/storage/mega_storage.rs index e721a8c39..ca0f86abe 100644 --- a/jupiter/src/storage/mega_storage.rs +++ b/jupiter/src/storage/mega_storage.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use futures::{stream, StreamExt}; use sea_orm::ActiveValue::NotSet; use sea_orm::{ ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, IntoActiveModel, QueryFilter, @@ -9,7 +9,8 @@ use sea_orm::{ use callisto::db_enums::{ConvType, MergeStatus}; use callisto::{ - mega_blob, mega_commit, mega_mr, mega_mr_comment, mega_mr_conv, mega_refs, mega_tree, raw_blob, + mega_blob, mega_commit, mega_mr, mega_mr_comment, mega_mr_conv, mega_refs, mega_tag, mega_tree, + raw_blob, }; use common::config::StorageConfig; use common::errors::MegaError; @@ -30,6 +31,15 @@ pub struct MegaStorage { pub raw_obj_threshold: usize, } +#[derive(Debug)] +struct GitObjects { + pub commits: Vec, + trees: Vec, + blobs: Vec, + raw_blobs: Vec, + tags: Vec, +} + impl MegaStorage { pub fn get_connection(&self) -> &DatabaseConnection { &self.connection @@ -227,49 +237,61 @@ impl MegaStorage { commit_id: &str, entry_list: Vec, ) -> Result<(), MegaError> { - let (commits, trees, blobs, raw_blobs, tags) = ( - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - Mutex::new(Vec::new()), - ); - - entry_list.par_iter().for_each(|entry| { - let raw_obj = entry.process_entry(); - let model = raw_obj.convert_to_mega_model(); - match model { - MegaObjectModel::Commit(commit) => { - commits.lock().unwrap().push(commit.into_active_model()) - } - MegaObjectModel::Tree(mut tree) => { - commit_id.clone_into(&mut tree.commit_id); - trees.lock().unwrap().push(tree.into_active_model()); + let git_objects = Arc::new(Mutex::new(GitObjects { + commits: Vec::new(), + trees: Vec::new(), + blobs: Vec::new(), + raw_blobs: Vec::new(), + tags: Vec::new(), + })); + + stream::iter(entry_list) + .for_each_concurrent(None, |entry| { + let git_objects = git_objects.clone(); + async move { + let raw_obj = entry.process_entry(); + let model = raw_obj.convert_to_mega_model(); + let mut git_objects = git_objects.lock().unwrap(); + match model { + MegaObjectModel::Commit(commit) => { + git_objects.commits.push(commit.into_active_model()) + } + MegaObjectModel::Tree(mut tree) => { + commit_id.clone_into(&mut tree.commit_id); + git_objects.trees.push(tree.into_active_model()); + } + MegaObjectModel::Blob(mut blob, raw) => { + commit_id.clone_into(&mut blob.commit_id); + git_objects.blobs.push(blob.clone().into_active_model()); + git_objects.raw_blobs.push(raw.into_active_model()); + } + MegaObjectModel::Tag(tag) => git_objects.tags.push(tag.into_active_model()), + } } - MegaObjectModel::Blob(mut blob, raw) => { - commit_id.clone_into(&mut blob.commit_id); - blobs.lock().unwrap().push(blob.clone().into_active_model()); - raw_blobs.lock().unwrap().push(raw.into_active_model()); - } - MegaObjectModel::Tag(tag) => tags.lock().unwrap().push(tag.into_active_model()), - } - }); + }) + .await; - batch_save_model(self.get_connection(), commits.into_inner().unwrap()) + let git_objects = Arc::try_unwrap(git_objects) + .expect("Failed to unwrap Arc") + .into_inner() + .unwrap(); + + batch_save_model(self.get_connection(), git_objects.commits) .await .unwrap(); - batch_save_model(self.get_connection(), trees.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.trees) .await .unwrap(); - batch_save_model(self.get_connection(), blobs.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.blobs) .await .unwrap(); - batch_save_model(self.get_connection(), raw_blobs.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.raw_blobs) .await .unwrap(); - batch_save_model(self.get_connection(), tags.into_inner().unwrap()) + batch_save_model(self.get_connection(), git_objects.tags) .await .unwrap(); + Ok(()) } @@ -396,21 +418,4 @@ impl MegaStorage { } #[cfg(test)] -mod test { - use std::rc::Rc; - - use venus::monorepo::mega_node::MegaNode; - - #[allow(unused)] - pub fn print_tree(root: Rc, depth: i32) { - println!( - "{:indent$}└── {}", - "", - root.name, - indent = (depth as usize) * 4 - ); - for child in root.children.borrow().iter() { - print_tree(child.clone(), depth + 1) - } - } -} +mod test {} diff --git a/lunar/src-tauri/.gitignore b/lunar/src-tauri/.gitignore index aba21e242..dbdc4af6d 100644 --- a/lunar/src-tauri/.gitignore +++ b/lunar/src-tauri/.gitignore @@ -1,3 +1,5 @@ # Generated by Cargo # will have compiled files and executables /target/ +/libs/ +/binaries/ \ No newline at end of file diff --git a/lunar/src-tauri/Cargo.toml b/lunar/src-tauri/Cargo.toml index 133d09eb6..984fc0daf 100644 --- a/lunar/src-tauri/Cargo.toml +++ b/lunar/src-tauri/Cargo.toml @@ -16,10 +16,12 @@ tauri-build = { version = "1.5.3", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.7.0", features = ["process-command-api"] } -mega = { workspace = true } +tauri = { version = "1.7.0", features = [ "shell-sidecar", "process-command-api"] } tokio = { workspace = true } +[dev-dependencies] +tokio = { workspace = true, features = ["macros"] } + [features] # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. # If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes. diff --git a/lunar/src-tauri/build.rs b/lunar/src-tauri/build.rs index 983f4f185..11484bb27 100644 --- a/lunar/src-tauri/build.rs +++ b/lunar/src-tauri/build.rs @@ -1,3 +1,5 @@ +use std::process::Command; + fn main() { #[cfg(target_os = "linux")] println!("cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN"); @@ -7,5 +9,61 @@ fn main() { // only for githut action check, according to [[feat] Prevent error when distDir doesn't exist](https://github.com/tauri-apps/tauri/issues/3142) // ../out is the default distDir std::fs::create_dir_all("../out").expect("failed to create out directory"); + std::fs::create_dir_all("./binaries").expect("failed to create binaries directory"); + std::fs::create_dir_all("./libs").expect("failed to create libs directory"); + + // Determine the platform-specific extension + let extension = if cfg!(target_os = "windows") { + ".exe" + } else { + "" + }; + // Execute the `rustc -vV` command to get Rust compiler information + let output = Command::new("rustc").arg("-vV").output().unwrap().stdout; + let rust_info = String::from_utf8(output).unwrap(); + + // Extract the target triple + let target_triple = rust_info + .lines() + .find_map(|line| line.strip_prefix("host: ")) + .ok_or("Failed to determine platform target triple") + .unwrap(); + + let sidecar_path = format!("./binaries/mega-{}{}", target_triple, extension); + + let debug_path = if cfg!(debug_assertions) { + "debug" + } else { + "release" + }; + + std::fs::copy(format!("../../target/{}/mega", debug_path), sidecar_path) + .expect("Run Cargo build for mega first"); + + // Copy libpipy due to target os + #[cfg(target_os = "macos")] + std::fs::copy( + format!("../../target/{}/libpipy.dylib", debug_path), + "./libs/libpipy.dylib", + ) + .expect("copy libpipy failed"); + + #[cfg(target_os = "linux")] + std::fs::copy( + format!("../../target/{}/libpipy.so", debug_path), + "./libs/libpipy.so", + ) + .expect("copy libpipy failed"); + + #[cfg(target_os = "windows")] + { + if cfg!(debug_assertions) { + std::fs::copy("../../target/debug/pipyd.dll", "./libs/pipyd.dll") + .expect("copy libpipy failed"); + } else { + std::fs::copy("../../target/release/pipy.dll", "./libs/pipy.dll") + .expect("copy libpipy failed"); + } + } tauri_build::build() } diff --git a/lunar/src-tauri/src/main.rs b/lunar/src-tauri/src/main.rs index cbed908ca..0188ae9b9 100644 --- a/lunar/src-tauri/src/main.rs +++ b/lunar/src-tauri/src/main.rs @@ -1,6 +1,7 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use std::env; use std::str::FromStr; use std::sync::Arc; @@ -9,10 +10,10 @@ use tauri::api::process::{Command, CommandChild, CommandEvent}; use tauri::State; use tokio::sync::Mutex; +#[derive(Default)] struct ServiceState { child: Option, } - #[derive(Debug, Deserialize, Clone)] struct MegaStartParams { pub bootstrap_node: String, @@ -28,9 +29,25 @@ impl Default for MegaStartParams { #[tauri::command] async fn start_mega_service( + handle: tauri::AppHandle, state: State<'_, Arc>>, params: MegaStartParams, -) -> Result<(), String> { +) -> Result { + let resource_path = handle + .path_resolver() + .resource_dir() + .expect("failed to resolve resource"); + let libs_dir = resource_path.join("libs"); + + #[cfg(target_os = "macos")] + std::env::set_var("DYLD_LIBRARY_PATH", libs_dir.to_str().unwrap()); + + #[cfg(target_os = "linux")] + std::env::set_var("LD_LIBRARY_PATH", libs_dir.to_str().unwrap()); + + #[cfg(target_os = "windows")] + std::env::set_var("PATH", format!("{};{}", libs_dir.to_str().unwrap(), std::env::var("PATH").unwrap())); + let mut service_state = state.lock().await; if service_state.child.is_some() { return Err("Service is already running".into()); @@ -48,15 +65,37 @@ async fn start_mega_service( .expect("Failed to spawn `Mega service`"); service_state.child = Some(child); - + let cloned_state = Arc::clone(&state); + // Sidecar output tauri::async_runtime::spawn(async move { while let Some(event) = rx.recv().await { - if let CommandEvent::Stdout(line) = event { - print!("{}", line); + match event { + CommandEvent::Stdout(line) => { + print!("{}", line); + } + CommandEvent::Stderr(line) => { + eprint!("Sidecar stderr: {}", line); + } + CommandEvent::Terminated(payload) => { + if let Some(code) = payload.code { + if code == 0 { + println!("Sidecar executed successfully."); + } else { + eprintln!("Sidecar failed with exit code: {}", code); + } + } else if let Some(signal) = payload.signal { + eprintln!("Sidecar terminated by signal: {}", signal); + } + // update ServiceState child + let mut service_state = cloned_state.lock().await; + service_state.child = None; + break; + } + _ => {} } } }); - Ok(()) + Ok(resource_path.to_str().unwrap().to_string()) } #[tauri::command] @@ -72,12 +111,12 @@ async fn stop_mega_service(state: State<'_, Arc>>) -> Result #[tauri::command] async fn restart_mega_service( + handle: tauri::AppHandle, state: State<'_, Arc>>, params: MegaStartParams, -) -> Result<(), String> { +) -> Result { stop_mega_service(state.clone()).await?; - start_mega_service(state, params).await?; - Ok(()) + start_mega_service(handle, state, params).await } #[tauri::command] @@ -89,7 +128,7 @@ async fn mega_service_status(state: State<'_, Arc>>) -> Resu fn main() { // let params = MegaStartParams::default(); tauri::Builder::default() - .manage(Arc::new(Mutex::new(ServiceState { child: None }))) + .manage(Arc::new(Mutex::new(ServiceState::default()))) .invoke_handler(tauri::generate_handler![ start_mega_service, stop_mega_service, diff --git a/lunar/src-tauri/tauri.conf.json b/lunar/src-tauri/tauri.conf.json index c8becffcf..28c2b4d9d 100644 --- a/lunar/src-tauri/tauri.conf.json +++ b/lunar/src-tauri/tauri.conf.json @@ -11,6 +11,15 @@ }, "tauri": { "allowlist": { + "shell": { + "sidecar": true, + "scope": [ + { + "name": "binaries/mega", + "sidecar": true + } + ] + }, "fs": { "scope": [ "$RESOURCE/*" @@ -23,11 +32,11 @@ "copyright": "", "appimage": {}, "deb": { - "files": { - "/usr/bin/libpipy.so": "../../target/release/libpipy.so" - } + "files": {} }, - "externalBin": [], + "externalBin": [ + "binaries/mega" + ], "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -40,9 +49,7 @@ "macOS": { "entitlements": null, "exceptionDomain": "", - "frameworks": [ - "../../target/release/libpipy.dylib" - ], + "frameworks": [], "providerShortName": null, "signingIdentity": null }, diff --git a/lunar/src-tauri/tauri.linux.conf.json b/lunar/src-tauri/tauri.linux.conf.json new file mode 100644 index 000000000..4bf585af6 --- /dev/null +++ b/lunar/src-tauri/tauri.linux.conf.json @@ -0,0 +1,9 @@ +{ + "tauri": { + "bundle": { + "resources": [ + "libs/libpipy.so" + ] + } + } +} \ No newline at end of file diff --git a/lunar/src-tauri/tauri.macos.conf.json b/lunar/src-tauri/tauri.macos.conf.json new file mode 100644 index 000000000..c0dc4e239 --- /dev/null +++ b/lunar/src-tauri/tauri.macos.conf.json @@ -0,0 +1,9 @@ +{ + "tauri": { + "bundle": { + "resources": [ + "libs/libpipy.dylib" + ] + } + } +} \ No newline at end of file diff --git a/lunar/src-tauri/tauri.windows.conf.json b/lunar/src-tauri/tauri.windows.conf.json new file mode 100644 index 000000000..0145aa8e2 --- /dev/null +++ b/lunar/src-tauri/tauri.windows.conf.json @@ -0,0 +1,9 @@ +{ + "tauri": { + "bundle": { + "resources": [ + "libs/pipy.dll" + ] + } + } +} \ No newline at end of file diff --git a/lunar/src/app/application-layout.tsx b/lunar/src/app/application-layout.tsx index a9f615bb3..c86265c1c 100644 --- a/lunar/src/app/application-layout.tsx +++ b/lunar/src/app/application-layout.tsx @@ -43,7 +43,7 @@ import { CodeBracketSquareIcon, ArchiveBoxArrowDownIcon, } from '@heroicons/react/20/solid' -import { invoke } from '@tauri-apps/api' +import { invoke } from '@tauri-apps/api/tauri' import { usePathname } from 'next/navigation' import { useState, useEffect } from 'react' import { Badge } from 'antd/lib' diff --git a/lunar/src/app/settings/page.tsx b/lunar/src/app/settings/page.tsx index c410732e0..163098b46 100644 --- a/lunar/src/app/settings/page.tsx +++ b/lunar/src/app/settings/page.tsx @@ -34,32 +34,17 @@ export default function Settings() { }, 6000); } - const startMega = async () => { - try { - await invoke('start_mega_service', { params: { params } }); - console.log('Mega service started successfully'); - } catch (error) { - console.error('Failed to start Mega service', error); - } - }; - const stopMega = async () => { - try { - await invoke('stop_mega_service'); - console.log('Mega service stopped successfully'); - } catch (error) { - console.error('Failed to stop Mega service', error); - } + invoke('stop_mega_service', { params: params }) + .then((message) => console.log("result:", message)) + .catch((err) => console.error("err:", err)); }; const restartMega = async () => { enterLoading(1); - try { - await invoke('restart_mega_service', { params: params }); - console.log('Mega service restarted successfully'); - } catch (error) { - console.error('Failed to restart Mega service', error); - } + invoke('restart_mega_service', { params: params }) + .then((message) => console.log("result:", message)) + .catch((err) => console.error("err:", err)); }; const handleInputChange = (e: React.ChangeEvent) => { diff --git a/mega/Cargo.toml b/mega/Cargo.toml index 7ac1e1537..bf0665ce1 100644 --- a/mega/Cargo.toml +++ b/mega/Cargo.toml @@ -40,7 +40,6 @@ async-trait = { workspace = true } bytes = { workspace = true } go-defer = { workspace = true } git2 = "0.19.0" -toml = "0.8.13" tempfile = "3.10.1" [build-dependencies] diff --git a/venus/src/monorepo/mega_node.rs b/venus/src/monorepo/mega_node.rs deleted file mode 100644 index 714216d87..000000000 --- a/venus/src/monorepo/mega_node.rs +++ /dev/null @@ -1,95 +0,0 @@ -use std::cell::RefCell; -use std::path::PathBuf; -use std::rc::Rc; - -use mercury::hash::SHA1; -use mercury::internal::object::blob::Blob; -use mercury::internal::object::tree::{Tree, TreeItemMode}; - -#[derive(Debug, Clone, PartialEq)] -pub struct MegaNode { - pub name: String, - pub path: PathBuf, - pub is_directory: bool, - pub children: RefCell>>, - pub id: SHA1, - pub mode: TreeItemMode, - pub commit_id: SHA1, -} - -impl MegaNode { - pub fn add_child(&self, node: &Rc) { - self.children.borrow_mut().push(Rc::clone(node)) - } - - // pub fn convert_to_mega_tree(&self, tree: &Tree) { - // let mut model: mega_tree::Model = self.to_owned().into(); - // model.tree_id = tree.id.to_plain_str(); - // model.sub_trees = tree.to_data().unwrap(); - // model.size = 0; - // } -} - -// Entity <==> Node <==> Git Objects -// impl From for mega_snapshot::Model { -// fn from(value: MegaNode) -> Self { -// mega_snapshot::Model { -// id: generate_id(), -// path: value.path.to_str().unwrap().to_owned(), -// name: value.name, -// import_dir: value.import_dir, -// tree_id: None, -// sub_trees: None, -// commit_id: None, -// size: 0, -// created_at: chrono::Utc::now().naive_utc(), -// updated_at: chrono::Utc::now().naive_utc(), -// } -// } -// } - -// impl From for mega_tree::Model { -// fn from(value: MegaNode) -> Self { -// mega_tree::Model { -// id: generate_id(), -// repo_id: 0, -// full_path: value.path.to_str().unwrap().to_owned(), -// tree_id: String::new(), -// sub_trees: Vec::new(), -// name: String::new(), -// parent_id: None, -// size: 0, -// commit_id: String::new(), -// created_at: chrono::Utc::now().naive_utc(), -// updated_at: chrono::Utc::now().naive_utc(), -// } -// } -// } - -impl From for MegaNode { - fn from(value: Tree) -> Self { - MegaNode { - name: String::new(), - path: PathBuf::new(), - is_directory: true, - children: RefCell::new(vec![]), - id: value.id, - mode: TreeItemMode::Tree, - commit_id: SHA1::default(), - } - } -} - -impl From for MegaNode { - fn from(value: Blob) -> Self { - MegaNode { - name: String::new(), - path: PathBuf::new(), - is_directory: false, - children: RefCell::new(vec![]), - id: value.id, - mode: TreeItemMode::Blob, - commit_id: SHA1::default(), - } - } -} diff --git a/venus/src/monorepo/mod.rs b/venus/src/monorepo/mod.rs index 4d9e130a8..9b0cc77df 100644 --- a/venus/src/monorepo/mod.rs +++ b/venus/src/monorepo/mod.rs @@ -1,4 +1,3 @@ +pub mod converter; pub mod mega_refs; pub mod mr; -pub mod converter; -pub mod mega_node; \ No newline at end of file