Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ sha256 = "1.5"
futures = "0.3.30"
futures-util = "0.3.30"
go-defer = "0.1.0"
russh = "0.44.0"
russh-keys = "0.44.0"
russh = "0.45.0"
russh-keys = "0.45.0"
axum = "0.7.5"
axum-extra = "0.9.3"
tower-http = "0.5.2"
Expand Down
2 changes: 1 addition & 1 deletion lunar/src-tauri/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn main() {
"release"
};

std::fs::copy(format!("../../target/{}/mega", debug_path), sidecar_path)
std::fs::copy(format!("../../target/{}/mega{}", debug_path, extension), sidecar_path)
.expect("Run Cargo build for mega first");

// Copy libpipy due to target os
Expand Down
102 changes: 55 additions & 47 deletions lunar/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,33 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use std::env;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::{Arc, Mutex};

use serde::Deserialize;
use tauri::api::process::{Command, CommandChild, CommandEvent};
use tauri::State;
use tokio::sync::Mutex;
use tauri::{Manager, State};

#[derive(Default)]
struct ServiceState {
child: Option<CommandChild>,
}
#[derive(Debug, Deserialize, Clone)]
struct MegaStartParams {
pub bootstrap_node: String,
}

impl Default for MegaStartParams {
fn default() -> Self {
Self {
bootstrap_node: String::from_str("http://34.84.172.121/relay").unwrap(),
impl Drop for ServiceState {
fn drop(&mut self) {
if let Some(child_process) = self.child.take() {
child_process
.kill()
.expect("Failed to kill sidecar process");
}
}
}

#[tauri::command]
async fn start_mega_service(
handle: tauri::AppHandle,
state: State<'_, Arc<Mutex<ServiceState>>>,
params: MegaStartParams,
) -> Result<String, String> {
#[derive(Debug, Deserialize, Clone, Default)]
struct MegaStartParams {
pub bootstrap_node: Option<String>,
}

fn set_up_lib(handle: tauri::AppHandle) {
let resource_path = handle
.path_resolver()
.resource_dir()
Expand All @@ -46,21 +42,34 @@ async fn start_mega_service(
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()));
std::env::set_var(
"PATH",
format!(
"{};{}",
libs_dir.to_str().unwrap(),
std::env::var("PATH").unwrap()
),
);
}

let mut service_state = state.lock().await;
#[tauri::command]
fn start_mega_service(
state: State<'_, Arc<Mutex<ServiceState>>>,
params: MegaStartParams,
) -> Result<(), String> {
let mut service_state = state.lock().unwrap();
if service_state.child.is_some() {
return Err("Service is already running".into());
}

let args = if let Some(ref addr) = params.bootstrap_node {
vec!["service", "http", "--bootstrap-node", addr]
} else {
vec!["service", "http"]
};
let (mut rx, child) = Command::new_sidecar("mega")
.expect("Failed to create `mega` binary command")
.args([
"service",
"http",
"--bootstrap-node",
&params.bootstrap_node,
])
.args(args)
.spawn()
.expect("Failed to spawn `Mega service`");

Expand All @@ -87,20 +96,20 @@ async fn start_mega_service(
eprintln!("Sidecar terminated by signal: {}", signal);
}
// update ServiceState child
let mut service_state = cloned_state.lock().await;
let mut service_state = cloned_state.lock().unwrap();
service_state.child = None;
break;
}
_ => {}
}
}
});
Ok(resource_path.to_str().unwrap().to_string())
Ok(())
}

#[tauri::command]
async fn stop_mega_service(state: State<'_, Arc<Mutex<ServiceState>>>) -> Result<(), String> {
let mut service_state = state.lock().await;
fn stop_mega_service(state: State<'_, Arc<Mutex<ServiceState>>>) -> Result<(), String> {
let mut service_state = state.lock().unwrap();
if let Some(child) = service_state.child.take() {
child.kill().map_err(|e| e.to_string())?;
} else {
Expand All @@ -110,23 +119,23 @@ async fn stop_mega_service(state: State<'_, Arc<Mutex<ServiceState>>>) -> Result
}

#[tauri::command]
async fn restart_mega_service(
handle: tauri::AppHandle,
fn restart_mega_service(
state: State<'_, Arc<Mutex<ServiceState>>>,
params: MegaStartParams,
) -> Result<String, String> {
stop_mega_service(state.clone()).await?;
start_mega_service(handle, state, params).await
) -> Result<(), String> {
stop_mega_service(state.clone())?;
start_mega_service(state, params)?;
Ok(())
}

#[tauri::command]
async fn mega_service_status(state: State<'_, Arc<Mutex<ServiceState>>>) -> Result<bool, String> {
let service_state = state.lock().await;
let service_state = state.lock().unwrap();
Ok(service_state.child.is_some())
}

fn main() {
// let params = MegaStartParams::default();
let params = MegaStartParams::default();
tauri::Builder::default()
.manage(Arc::new(Mutex::new(ServiceState::default())))
.invoke_handler(tauri::generate_handler![
Expand All @@ -135,16 +144,15 @@ fn main() {
restart_mega_service,
mega_service_status
])
.setup(|_| {
// let app_handle = app.handle();
// let state = app.state::<Arc<Mutex<ServiceState>>>().clone();
// tauri::async_runtime::spawn(async move {
// if let Err(e) = start_mega_service(state, params).await {
// eprintln!("Failed to restart rust_service: {}", e);
// } else {
// println!("Rust service restarted successfully");
// }
// });
.setup(|app| {
let app_handle = app.handle().clone();
set_up_lib(app_handle);
let state = app.state::<Arc<Mutex<ServiceState>>>().clone();
if let Err(e) = start_mega_service(state, params) {
eprintln!("Failed to restart rust_service: {}", e);
} else {
println!("Rust service restarted successfully");
}
Ok(())
})
.run(tauri::generate_context!())
Expand Down
35 changes: 34 additions & 1 deletion lunar/src/app/api/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const fetcher = async url => {

export function useTreeCommitInfo(path) {
const { data, error, isLoading } = useSWR(`${endpoint}/api/v1/mono/tree/commit-info?path=${path}`, fetcher, {
dedupingInterval: 1000,
dedupingInterval: 30000,
})
return {
tree: data,
Expand All @@ -48,6 +48,39 @@ export function useBlobContent(path) {
}
}

export function useMRList(status) {
const { data, error, isLoading } = useSWR(`${endpoint}/api/v1/mono/mr/list?status=${status}`, fetcher, {
dedupingInterval: 60000,
})
return {
mrList: data,
isMRLoading: isLoading,
isMRError: error,
}
}

export function useMRDetail(id) {
const { data, error, isLoading } = useSWR(`${endpoint}/api/v1/mono/mr/${id}/detail`, fetcher, {
dedupingInterval: 60000,
})
return {
mrDetail: data,
isMRLoading: isLoading,
isMRError: error,
}
}

export function useMRFiles(id) {
const { data, error, isLoading } = useSWR(`${endpoint}/api/v1/mono/mr/${id}/files`, fetcher, {
dedupingInterval: 60000,
})
return {
mrFiles: data,
isMRLoading: isLoading,
isMRError: error,
}
}

export function useRepoList() {
const { data, error, isLoading } = useSWR(`${relay}/relay/api/v1/repo_list`, fetcher, {
dedupingInterval: 30000,
Expand Down
9 changes: 9 additions & 0 deletions lunar/src/app/blob/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@ import Bread from '@/components/BreadCrumb';
import { useSearchParams } from 'next/navigation';
import { useBlobContent } from '../api/fetcher';
import { Skeleton } from "antd/lib";
import { Suspense } from 'react'


export default function BlobPage() {
return (
<Suspense>
<Blob />
</Suspense>
)
}

function Blob() {
const searchParams = useSearchParams();
const path = searchParams.get('path');

Expand Down
27 changes: 27 additions & 0 deletions lunar/src/app/mr/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client'
import MergeDetail from "@/components/MergeDetail";
import { useMRDetail } from "../api/fetcher";
import { Skeleton } from "antd/lib";
import { useSearchParams } from "next/navigation";
import { Suspense } from 'react'

export default function Page() {
return (
<Suspense>
<MRDetailPage />
</Suspense>
);
}

function MRDetailPage() {
const searchParams = useSearchParams();
const id = searchParams.get('id');
const { mrDetail, isMRLoading, isMRError } = useMRDetail(id);
if (isMRLoading) return <Skeleton />;

return (
<div>
<MergeDetail mrDetail={mrDetail.data} />
</div>
)
}
Loading