mirror of
https://github.com/open-goal/launcher.git
synced 2024-10-20 04:57:38 -04:00
f/logs: only show the last 250
lines in the job logs
This commit is contained in:
parent
93941a5cb3
commit
f84a7c6403
10
src-tauri/Cargo.lock
generated
10
src-tauri/Cargo.lock
generated
|
@ -2273,6 +2273,7 @@ dependencies = [
|
|||
"futures-util",
|
||||
"log",
|
||||
"reqwest",
|
||||
"rev_buf_reader",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
|
@ -2902,6 +2903,15 @@ dependencies = [
|
|||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rev_buf_reader"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c0f2e47e00e29920959826e2e1784728a3780d1a784247be5257258cc75f910"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfd"
|
||||
version = "0.10.0"
|
||||
|
|
|
@ -32,6 +32,7 @@ wgpu = "0.15.1"
|
|||
walkdir = "2.3.2"
|
||||
dir-diff = "0.3.2"
|
||||
thiserror = "1.0.38"
|
||||
rev_buf_reader = "0.3.0"
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
|
|
|
@ -12,7 +12,7 @@ use tauri::Manager;
|
|||
|
||||
use crate::{
|
||||
config::LauncherConfig,
|
||||
util::file::{create_dir, overwrite_dir, read_lines_in_file},
|
||||
util::file::{create_dir, overwrite_dir, read_last_lines_from_file, read_lines_in_file},
|
||||
};
|
||||
|
||||
use super::CommandError;
|
||||
|
@ -244,9 +244,16 @@ pub async fn update_data_directory(
|
|||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
struct LogPayload {
|
||||
stdout: String,
|
||||
#[tauri::command]
|
||||
pub async fn get_end_of_logs(app_handle: tauri::AppHandle) -> Result<String, CommandError> {
|
||||
Ok(read_last_lines_from_file(
|
||||
&app_handle
|
||||
.path_resolver()
|
||||
.app_log_dir()
|
||||
.unwrap()
|
||||
.join("extractor.log"),
|
||||
250,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
@ -283,21 +290,6 @@ pub async fn extract_and_validate_iso(
|
|||
.stdout(log_file.try_clone().unwrap())
|
||||
.stderr(log_file.try_clone().unwrap())
|
||||
.output()?;
|
||||
// TODO - we should instead capture the logs while simulanteously streaming them to a file
|
||||
// right now we aren't so I just read the file after it's done
|
||||
app_handle.emit_all(
|
||||
"updateJobLogs",
|
||||
LogPayload {
|
||||
stdout: read_lines_in_file(
|
||||
&app_handle
|
||||
.path_resolver()
|
||||
.app_log_dir()
|
||||
.unwrap()
|
||||
.join("extractor.log"),
|
||||
)
|
||||
.expect("TODO"),
|
||||
},
|
||||
)?;
|
||||
match output.status.code() {
|
||||
Some(code) => {
|
||||
if code == 0 {
|
||||
|
@ -329,6 +321,7 @@ pub async fn run_decompiler(
|
|||
app_handle: tauri::AppHandle,
|
||||
path_to_iso: String,
|
||||
game_name: String,
|
||||
truncate_logs: bool,
|
||||
) -> Result<InstallStepOutput, CommandError> {
|
||||
let config_lock = config.lock().await;
|
||||
let config_info = common_prelude(&config_lock)?;
|
||||
|
@ -345,7 +338,7 @@ pub async fn run_decompiler(
|
|||
.to_string();
|
||||
}
|
||||
|
||||
let log_file = create_log_file(&app_handle, "extractor.log", true)?;
|
||||
let log_file = create_log_file(&app_handle, "extractor.log", !truncate_logs)?;
|
||||
let output = Command::new(&exec_info.executable_path)
|
||||
.creation_flags(0x08000000)
|
||||
.args([
|
||||
|
@ -358,21 +351,6 @@ pub async fn run_decompiler(
|
|||
.stderr(log_file)
|
||||
.current_dir(exec_info.executable_dir)
|
||||
.output()?;
|
||||
// TODO - we should instead capture the logs while simulanteously streaming them to a file
|
||||
// right now we aren't so I just read the file after it's done
|
||||
app_handle.emit_all(
|
||||
"updateJobLogs",
|
||||
LogPayload {
|
||||
stdout: read_lines_in_file(
|
||||
&app_handle
|
||||
.path_resolver()
|
||||
.app_log_dir()
|
||||
.unwrap()
|
||||
.join("extractor.log"),
|
||||
)
|
||||
.expect("TODO"),
|
||||
},
|
||||
)?;
|
||||
match output.status.code() {
|
||||
Some(code) => {
|
||||
if code == 0 {
|
||||
|
@ -404,6 +382,7 @@ pub async fn run_compiler(
|
|||
app_handle: tauri::AppHandle,
|
||||
path_to_iso: String,
|
||||
game_name: String,
|
||||
truncate_logs: bool,
|
||||
) -> Result<InstallStepOutput, CommandError> {
|
||||
let config_lock = config.lock().await;
|
||||
let config_info = common_prelude(&config_lock)?;
|
||||
|
@ -420,7 +399,7 @@ pub async fn run_compiler(
|
|||
.to_string();
|
||||
}
|
||||
|
||||
let log_file = create_log_file(&app_handle, "extractor.log", true)?;
|
||||
let log_file = create_log_file(&app_handle, "extractor.log", !truncate_logs)?;
|
||||
let output = Command::new(&exec_info.executable_path)
|
||||
.creation_flags(0x08000000)
|
||||
.args([
|
||||
|
@ -433,21 +412,6 @@ pub async fn run_compiler(
|
|||
.stderr(log_file)
|
||||
.current_dir(exec_info.executable_dir)
|
||||
.output()?;
|
||||
// TODO - we should instead capture the logs while simulanteously streaming them to a file
|
||||
// right now we aren't so I just read the file after it's done
|
||||
app_handle.emit_all(
|
||||
"updateJobLogs",
|
||||
LogPayload {
|
||||
stdout: read_lines_in_file(
|
||||
&app_handle
|
||||
.path_resolver()
|
||||
.app_log_dir()
|
||||
.unwrap()
|
||||
.join("extractor.log"),
|
||||
)
|
||||
.expect("TODO"),
|
||||
},
|
||||
)?;
|
||||
match output.status.code() {
|
||||
Some(code) => {
|
||||
if code == 0 {
|
||||
|
|
|
@ -78,6 +78,7 @@ fn main() {
|
|||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::binaries::update_data_directory,
|
||||
commands::binaries::get_end_of_logs,
|
||||
commands::binaries::extract_and_validate_iso,
|
||||
commands::binaries::launch_game,
|
||||
commands::binaries::open_repl,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::PathBuf;
|
||||
use std::{io::BufRead, path::PathBuf};
|
||||
|
||||
pub fn delete_dir(path: &PathBuf) -> Result<(), std::io::Error> {
|
||||
if path.exists() && path.is_dir() {
|
||||
|
@ -36,3 +36,21 @@ pub fn overwrite_dir(src: &PathBuf, dst: &PathBuf) -> Result<(), fs_extra::error
|
|||
pub fn read_lines_in_file(path: &PathBuf) -> Result<String, Box<dyn std::error::Error>> {
|
||||
Ok(std::fs::read_to_string(path)?)
|
||||
}
|
||||
|
||||
pub fn read_last_lines_from_file(path: &PathBuf, lines: usize) -> Result<String, std::io::Error> {
|
||||
if !path.exists() {
|
||||
return Ok("".to_owned());
|
||||
}
|
||||
let buf = rev_buf_reader::RevBufReader::new(std::fs::File::open(path)?);
|
||||
Ok(
|
||||
buf
|
||||
.lines()
|
||||
.take(lines)
|
||||
.map(|l| l.unwrap_or("".to_owned()))
|
||||
.collect::<Vec<String>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
import type { Job } from "$lib/jobs/jobs";
|
||||
import { getInternalName, type SupportedGame } from "$lib/constants";
|
||||
import {
|
||||
getEndOfLogs,
|
||||
runCompiler,
|
||||
runDecompiler,
|
||||
updateDataDirectory,
|
||||
} from "$lib/rpc/binaries";
|
||||
import { finalizeInstallation } from "$lib/rpc/config";
|
||||
import { generateSupportPackage } from "$lib/rpc/support";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
|
||||
export let activeGame: SupportedGame;
|
||||
export let jobType: Job;
|
||||
|
@ -29,10 +29,6 @@
|
|||
// It's used to provide almost the same interface as the normal installation, with logs, etc
|
||||
// but for arbitrary jobs. Such as updating versions, decompiling, or compiling.
|
||||
onMount(async () => {
|
||||
const unlistenLogListener = await listen("updateJobLogs", async (event) => {
|
||||
progressTracker.updateLogs(event.payload["stdout"]);
|
||||
});
|
||||
|
||||
if (jobType === "decompile") {
|
||||
installationError = undefined;
|
||||
progressTracker.init([
|
||||
|
@ -46,7 +42,8 @@
|
|||
},
|
||||
]);
|
||||
progressTracker.start();
|
||||
let resp = await runDecompiler("", getInternalName(activeGame));
|
||||
let resp = await runDecompiler("", getInternalName(activeGame), true);
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
@ -67,7 +64,8 @@
|
|||
},
|
||||
]);
|
||||
progressTracker.start();
|
||||
let resp = await runCompiler("", getInternalName(activeGame));
|
||||
let resp = await runCompiler("", getInternalName(activeGame), true);
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
@ -97,13 +95,15 @@
|
|||
]);
|
||||
progressTracker.start();
|
||||
let resp = await updateDataDirectory(getInternalName(activeGame));
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
return;
|
||||
}
|
||||
progressTracker.proceed();
|
||||
resp = await runDecompiler("", getInternalName(activeGame));
|
||||
resp = await runDecompiler("", getInternalName(activeGame), true);
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
@ -111,6 +111,7 @@
|
|||
}
|
||||
progressTracker.proceed();
|
||||
resp = await runCompiler("", getInternalName(activeGame));
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
import { Alert, Button } from "flowbite-svelte";
|
||||
import {
|
||||
extractAndValidateISO,
|
||||
getEndOfLogs,
|
||||
runCompiler,
|
||||
runDecompiler,
|
||||
} from "$lib/rpc/binaries";
|
||||
|
@ -26,7 +27,6 @@
|
|||
import { progressTracker } from "$lib/stores/ProgressStore";
|
||||
import { generateSupportPackage } from "$lib/rpc/support";
|
||||
import { isOpenGLVersionSupported } from "$lib/sidecars/glewinfo";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
|
||||
export let activeGame: SupportedGame;
|
||||
|
||||
|
@ -45,10 +45,6 @@
|
|||
await setOpenGLRequirementMet(isOpenGLMet);
|
||||
}
|
||||
requirementsMet = isAvxMet && isOpenGLMet;
|
||||
|
||||
const unlistenLogListener = await listen("updateJobLogs", async (event) => {
|
||||
progressTracker.updateLogs(event.payload["stdout"]);
|
||||
});
|
||||
});
|
||||
|
||||
async function install(viaFolder: boolean) {
|
||||
|
@ -88,6 +84,7 @@
|
|||
sourcePath,
|
||||
getInternalName(activeGame)
|
||||
);
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
@ -95,6 +92,7 @@
|
|||
}
|
||||
progressTracker.proceed();
|
||||
resp = await runDecompiler(sourcePath, getInternalName(activeGame));
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
@ -102,6 +100,7 @@
|
|||
}
|
||||
progressTracker.proceed();
|
||||
resp = await runCompiler(sourcePath, getInternalName(activeGame));
|
||||
progressTracker.updateLogs(await getEndOfLogs());
|
||||
if (!resp.success) {
|
||||
progressTracker.halt();
|
||||
installationError = resp.msg;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
class="bg-slate-900 px-4 max-h-60 overflow-y-scroll scrollbar"
|
||||
>
|
||||
<p class="py-4 text-clip overflow-hidden font-mono log-output">
|
||||
...Last 250 Lines:
|
||||
<br />
|
||||
{@html convertLogColors($progressTracker.logs)}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -24,6 +24,18 @@ export async function updateDataDirectory(
|
|||
}
|
||||
}
|
||||
|
||||
export async function getEndOfLogs(): Promise<string> {
|
||||
try {
|
||||
return await invoke("get_end_of_logs", {});
|
||||
} catch (e) {
|
||||
console.log(
|
||||
"[OG]: Unexpected error encountered when updating data directory",
|
||||
e
|
||||
);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export async function extractAndValidateISO(
|
||||
pathToIso: string,
|
||||
gameName: string
|
||||
|
@ -47,12 +59,14 @@ export async function extractAndValidateISO(
|
|||
|
||||
export async function runDecompiler(
|
||||
pathToIso: string,
|
||||
gameName: string
|
||||
gameName: string,
|
||||
truncateLogs: boolean = false
|
||||
): Promise<InstallationOutput> {
|
||||
try {
|
||||
return await invoke("run_decompiler", {
|
||||
pathToIso: pathToIso,
|
||||
gameName: gameName,
|
||||
truncateLogs: truncateLogs,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(
|
||||
|
@ -68,12 +82,14 @@ export async function runDecompiler(
|
|||
|
||||
export async function runCompiler(
|
||||
pathToIso: string,
|
||||
gameName: string
|
||||
gameName: string,
|
||||
truncateLogs: boolean = false
|
||||
): Promise<InstallationOutput> {
|
||||
try {
|
||||
return await invoke("run_compiler", {
|
||||
pathToIso: pathToIso,
|
||||
gameName: gameName,
|
||||
truncateLogs: truncateLogs,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(
|
||||
|
|
Loading…
Reference in a new issue