From 968004a515ba851b4575c8ab6d0fb8929746095f Mon Sep 17 00:00:00 2001 From: TheAlan404 Date: Sat, 11 Nov 2023 15:03:18 +0300 Subject: [PATCH] yea --- examples/quilt/server.toml | 8 ++- src/hot_reload/mod.rs | 97 ++++++++++++++++++++++++++++++------- src/model/servertype/mod.rs | 16 ++++-- 3 files changed, 93 insertions(+), 28 deletions(-) diff --git a/examples/quilt/server.toml b/examples/quilt/server.toml index 2f3d922..ff1a9ca 100644 --- a/examples/quilt/server.toml +++ b/examples/quilt/server.toml @@ -20,11 +20,9 @@ type = "modrinth" id = "create-fabric" version = "wKEEi1qX" -[[mods]] -type = "modrinth" -id = "qsl" -version = "BTCxVi75" - [markdown] files = ["README.md"] auto_update = false + +[options] +upload_to_mclogs = true diff --git a/src/hot_reload/mod.rs b/src/hot_reload/mod.rs index 7dc8e92..c187dea 100644 --- a/src/hot_reload/mod.rs +++ b/src/hot_reload/mod.rs @@ -1,6 +1,6 @@ -use std::{process::Stdio, time::Duration, path::PathBuf, sync::{Mutex, Arc}}; +use std::{process::{Stdio, ExitStatus}, time::Duration, path::PathBuf, sync::{Mutex, Arc}}; -use anyhow::{Result, Context}; +use anyhow::{Result, Context, bail, anyhow}; use console::style; use dialoguer::theme::ColorfulTheme; use indicatif::ProgressBar; @@ -42,6 +42,20 @@ async fn try_read_line(opt: &mut Option) -> Result> { + match opt { + Some(c) => Ok(Some(c.wait().await?)), + None => Ok(None), + } +} + +pub enum TestResult { + Ongoing, + Success, + Failed, + Crashed, +} + // TODO // [x] fix stdout nesting for some reason // [x] commands are not being sent properly @@ -86,11 +100,12 @@ impl<'a> DevSession<'a> { let mut is_stopping = false; let mut test_passed = false; + let mut test_result = TestResult::Ongoing; let mut exit_status = None; let mut stdin_lines = tokio::io::BufReader::new(tokio::io::stdin()).lines(); - loop { + 'l: loop { tokio::select! { Some(cmd) = rx.recv() => { match cmd { @@ -112,7 +127,6 @@ impl<'a> DevSession<'a> { exit_status = None; } Command::SendCommand(command) => { - self.builder.app.info(&format!("Sending command: {command}"))?; if let Some(ref mut child) = &mut child { if let Some(ref mut stdin) = &mut child.stdin { let _ = stdin.write_all(command.as_bytes()).await; @@ -181,7 +195,7 @@ impl<'a> DevSession<'a> { } Command::EndSession => { self.builder.app.info("Ending session...")?; - break; + break 'l; } } }, @@ -190,16 +204,24 @@ impl<'a> DevSession<'a> { if self.test_mode && !is_stopping - && !test_passed - && s.contains("]: Done") - && s.ends_with("For help, type \"help\"") { - test_passed = true; - - self.builder.app.success("Test passed!"); - - tx.send(Command::SendCommand("stop\nend\n".to_owned())).await?; - tx.send(Command::WaitUntilExit).await?; - tx.send(Command::EndSession).await?; + && !test_passed { + + if s.contains("]: Done") && s.ends_with("For help, type \"help\"") { + test_passed = true; + test_result = TestResult::Success; + + self.builder.app.success("Test passed!")?; + + tx.send(Command::SendCommand("stop\nend\n".to_owned())).await?; + tx.send(Command::WaitUntilExit).await?; + tx.send(Command::EndSession).await?; + } else if s == "---- end of report ----" { + self.builder.app.info("Server crashed!")?; + test_result = TestResult::Crashed; + + tx.send(Command::WaitUntilExit).await?; + tx.send(Command::EndSession).await?; + } } mp.suspend(|| { @@ -219,10 +241,20 @@ impl<'a> DevSession<'a> { } } }, + status = try_wait_child(&mut child) => { + exit_status = status.unwrap_or(None); + + self.builder.app.info("Server process exited")?; + + if self.test_mode { + tx.send(Command::WaitUntilExit).await?; + tx.send(Command::EndSession).await?; + } + }, _ = tokio::signal::ctrl_c() => { if !is_stopping { self.builder.app.info("Stopping development session...")?; - break; + break 'l; } } } @@ -258,6 +290,15 @@ impl<'a> DevSession<'a> { } } } + + match test_result { + TestResult::Crashed => { + println!( + " - Server crashed" + ); + } + _ => {} + } }); if self.builder.app.server.options.upload_to_mclogs { @@ -266,7 +307,27 @@ impl<'a> DevSession<'a> { pb.enable_steady_tick(Duration::from_millis(250)); - let log_path = self.builder.output_dir.join("logs").join("latest.log"); + let log_path = match test_result { + TestResult::Crashed => { + let folder = self.builder.output_dir.join("crash-reports"); + if !folder.exists() { + bail!("crash-reports folder doesn't exist, cant upload to mclo.gs"); + } + + // get latest crash report + let (report_path, _) = folder.read_dir()? + .into_iter() + .filter_map(|f| f.ok()) + .filter_map(|f| Some((f.path(), f.metadata().ok()?.modified().ok()?))) + .max_by_key(|(_, t)| t.clone()) + .ok_or(anyhow!("can't find crash report"))?; + + report_path + } + _ => { + self.builder.output_dir.join("logs").join("latest.log") + } + }; if log_path.exists() { let content = std::fs::read_to_string(&log_path) @@ -276,7 +337,7 @@ impl<'a> DevSession<'a> { drop(content); pb.finish_and_clear(); - self.builder.app.success("Log uploaded to mclo.gs"); + self.builder.app.success("Log uploaded to mclo.gs")?; mp.suspend(|| { println!(); println!(" -- [ {} ] --", log.url); diff --git a/src/model/servertype/mod.rs b/src/model/servertype/mod.rs index bc68877..6952b71 100644 --- a/src/model/servertype/mod.rs +++ b/src/model/servertype/mod.rs @@ -115,6 +115,7 @@ impl ServerType { } } + // TODO: move this to somewhere else, like BuildContext pub async fn get_install_method( &self, app: &App, @@ -196,6 +197,7 @@ impl ServerType { }) } + // TODO: move this to somewhere else, like BuildContext pub async fn get_startup_method( &self, app: &App, @@ -231,6 +233,7 @@ impl ServerType { }) } + // TODO: move to ModrinthAPI pub fn get_modrinth_facets(&self, mcver: &str) -> Result { let mut arr: Vec> = vec![]; @@ -245,6 +248,7 @@ impl ServerType { Ok(serde_json::to_string(&arr)?) } + // TODO: move to ModrinthAPI pub fn get_modrinth_name(&self) -> Option { match self { Self::Fabric { .. } => Some("fabric"), @@ -262,6 +266,7 @@ impl ServerType { }.map(|o| o.to_owned()) } + // TODO: move to HangarAPI pub fn get_hangar_platform(&self) -> Option { match self { Self::Waterfall {} => Some(mcapi::hangar::Platform::Waterfall), @@ -274,6 +279,7 @@ impl ServerType { } } + // TODO: move to HangarAPI pub fn get_hangar_versions_filter(&self, mcver: &str) -> mcapi::hangar::VersionsFilter { let platform = self.get_hangar_platform(); mcapi::hangar::VersionsFilter { @@ -302,11 +308,11 @@ impl ToString for ServerType { ServerType::Vanilla { } => String::from("Vanilla"), ServerType::PaperMC { project, build } => format!("{project} build {build}"), ServerType::Purpur { build } => format!("Purpur build {build}"), - ServerType::Fabric { loader, installer } => format!("Fabric v{loader}"), - ServerType::Quilt { loader, installer } => format!("Quilt v{loader}"), + ServerType::Fabric { loader, .. } => format!("Fabric v{loader}"), + ServerType::Quilt { loader, .. } => format!("Quilt v{loader}"), ServerType::NeoForge { loader } => format!("NeoForge v{loader}"), ServerType::Forge { loader } => format!("Forge v{loader}"), - ServerType::BuildTools { software, args } => format!("(BuildTools) {software}"), + ServerType::BuildTools { software, .. } => format!("(BuildTools) {software}"), ServerType::Paper { } => format!("Paper"), ServerType::Velocity { } => format!("Velocity"), ServerType::Waterfall { } => format!("Waterfall"), @@ -326,10 +332,10 @@ impl Resolvable for ServerType { ServerType::PaperMC { project, build } => app.papermc().resolve_source(project, version, build).await, ServerType::Purpur { build } => app.purpur().resolve_source(version, build).await, ServerType::Fabric { loader, installer } => app.fabric().resolve_source(loader, installer).await, - ServerType::Quilt { loader, installer } => app.quilt().resolve_installer(installer).await, + ServerType::Quilt { installer, .. } => app.quilt().resolve_installer(installer).await, ServerType::NeoForge { loader } => app.neoforge().resolve_source(loader).await, ServerType::Forge { loader } => app.forge().resolve_source(loader).await, - ServerType::BuildTools { software, args } => buildtools().resolve_source(app).await, + ServerType::BuildTools { .. } => buildtools().resolve_source(app).await, ServerType::Paper { } => app.papermc().resolve_source("paper", version, "latest").await, ServerType::Velocity { } => app.papermc().resolve_source("velocity", version, "latest").await, ServerType::Waterfall { } => app.papermc().resolve_source("waterfall", version, "latest").await,