mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
refactor: improved error handling for base bin discovery process
This commit is contained in:
parent
52e71850d1
commit
93b950ce10
1 changed files with 87 additions and 40 deletions
127
src/cli/build.rs
127
src/cli/build.rs
|
@ -4,12 +4,17 @@ use std::{
|
||||||
process::ExitCode,
|
process::ExitCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{bail, Context, Error, Result};
|
||||||
|
use async_compression::tokio::bufread::DeflateDecoder;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use console::style;
|
use console::style;
|
||||||
use directories::BaseDirs;
|
use directories::BaseDirs;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use tokio::{fs, io::AsyncWriteExt as _};
|
use thiserror::Error;
|
||||||
|
use tokio::{
|
||||||
|
fs,
|
||||||
|
io::{AsyncReadExt, AsyncWriteExt as _},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::standalone::metadata::Metadata;
|
use crate::standalone::metadata::Metadata;
|
||||||
|
|
||||||
|
@ -41,6 +46,9 @@ pub struct BuildCommand {
|
||||||
pub base: Option<PathBuf>,
|
pub base: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Currently, the file we are patching is user provided, so we should
|
||||||
|
// probably check whether the binary is a valid lune base binary first
|
||||||
|
|
||||||
impl BuildCommand {
|
impl BuildCommand {
|
||||||
pub async fn run(self) -> Result<ExitCode> {
|
pub async fn run(self) -> Result<ExitCode> {
|
||||||
let mut output_path = self
|
let mut output_path = self
|
||||||
|
@ -55,7 +63,24 @@ impl BuildCommand {
|
||||||
.context("failed to read input file")?;
|
.context("failed to read input file")?;
|
||||||
|
|
||||||
// Dynamically derive the base executable path based on the CLI arguments provided
|
// Dynamically derive the base executable path based on the CLI arguments provided
|
||||||
let base_exe_path = get_base_exe_path(self.base, self.target, &mut output_path).await;
|
let base_exe_path = match get_base_exe_path(self.base, self.target, &mut output_path).await
|
||||||
|
{
|
||||||
|
Ok(path) => Some(path),
|
||||||
|
Err(err) => {
|
||||||
|
let inner_err = err.downcast::<BasePathDiscoveryError<()>>();
|
||||||
|
|
||||||
|
if let Err(other_err) = inner_err {
|
||||||
|
bail!(
|
||||||
|
"Encountered an error while handling cross-compilation flags: {}",
|
||||||
|
other_err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there the downcasted error was ok, it is safe to continue since
|
||||||
|
// neither the --base nor the --target flags were set
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Read the contents of the lune interpreter as our starting point
|
// Read the contents of the lune interpreter as our starting point
|
||||||
println!(
|
println!(
|
||||||
|
@ -94,27 +119,39 @@ async fn write_executable_file_to(path: impl AsRef<Path>, bytes: impl AsRef<[u8]
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Error, PartialEq)]
|
||||||
|
pub enum BasePathDiscoveryError<T> {
|
||||||
|
#[error("decompression error")]
|
||||||
|
Decompression(T),
|
||||||
|
#[error("precompiled base for target not found for {target}")]
|
||||||
|
TargetNotFound { target: String },
|
||||||
|
#[error("failed to download precompiled binary base")]
|
||||||
|
DownloadError(T),
|
||||||
|
#[error("a generic error related to an io operation occurred")]
|
||||||
|
IoError(T),
|
||||||
|
#[error("neither a custom base path or precompiled target name provided")]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_base_exe_path(
|
async fn get_base_exe_path(
|
||||||
base: Option<PathBuf>,
|
base: Option<PathBuf>,
|
||||||
target: Option<String>,
|
target: Option<String>,
|
||||||
output_path: &mut PathBuf,
|
output_path: &mut PathBuf,
|
||||||
) -> Option<PathBuf> {
|
) -> Result<PathBuf> {
|
||||||
if base.is_some() {
|
if let Some(base) = base {
|
||||||
output_path.set_extension(
|
output_path.set_extension(
|
||||||
base.clone()
|
base.extension()
|
||||||
.unwrap()
|
|
||||||
.extension()
|
|
||||||
.expect("failed to get extension of base binary"),
|
.expect("failed to get extension of base binary"),
|
||||||
);
|
);
|
||||||
|
|
||||||
base
|
Ok(base)
|
||||||
} else if let Some(target_inner) = target {
|
} else if let Some(target_inner) = target {
|
||||||
let target_exe_extension = match target_inner.as_str() {
|
let target_exe_extension = match target_inner.as_str() {
|
||||||
"windows-x86_64" => "exe",
|
"windows-x86_64" => "exe",
|
||||||
_ => "bin",
|
_ => "bin",
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = TARGET_BASE_DIR.join(format!("lune-{}.{}", target_inner, target_exe_extension));
|
let path = TARGET_BASE_DIR.join(format!("lune-{target_inner}.{target_exe_extension}"));
|
||||||
|
|
||||||
output_path.set_extension(if target_exe_extension == "bin" {
|
output_path.set_extension(if target_exe_extension == "bin" {
|
||||||
""
|
""
|
||||||
|
@ -125,7 +162,7 @@ async fn get_base_exe_path(
|
||||||
if !TARGET_BASE_DIR.exists() {
|
if !TARGET_BASE_DIR.exists() {
|
||||||
fs::create_dir_all(TARGET_BASE_DIR.to_path_buf())
|
fs::create_dir_all(TARGET_BASE_DIR.to_path_buf())
|
||||||
.await
|
.await
|
||||||
.ok()?;
|
.map_err(BasePathDiscoveryError::IoError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
|
@ -150,34 +187,44 @@ async fn get_base_exe_path(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Maybe we should use the custom net client used in `@lune/net`
|
// Maybe we should use the custom net client used in `@lune/net`
|
||||||
let dl_req = match reqwest::get(release_url).await {
|
let resp = reqwest::get(release_url).await.map_err(|err| {
|
||||||
Err(_) => {
|
eprintln!(
|
||||||
eprintln!(
|
" {} Unable to download base binary found for target `{}`",
|
||||||
" {} Unable to download base binary found for target `{}`",
|
style("Download").red().bold(),
|
||||||
style("Download").red().bold(),
|
target_inner,
|
||||||
target_inner,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
return None;
|
BasePathDiscoveryError::DownloadError::<Error>(err.into())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let resp_status = resp.status();
|
||||||
|
|
||||||
|
if resp_status != 200 && !resp_status.is_redirection() {
|
||||||
|
eprintln!(
|
||||||
|
" {} No precompiled base binary found for target `{}`",
|
||||||
|
style("Download").red().bold(),
|
||||||
|
target_inner
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("{}: {}", style("HINT").yellow(), style("Perhaps try providing a path to self-compiled target with the `--base` flag").italic());
|
||||||
|
|
||||||
|
return Err(BasePathDiscoveryError::TargetNotFound::<String> {
|
||||||
|
target: target_inner,
|
||||||
}
|
}
|
||||||
Ok(resp) => {
|
.into());
|
||||||
let resp_status = resp.status();
|
}
|
||||||
|
|
||||||
if resp_status != 200 && !resp_status.is_redirection() {
|
let compressed_reader = resp
|
||||||
eprintln!(
|
.bytes()
|
||||||
" {} No precompiled base binary found for target `{}`",
|
.await
|
||||||
style("Download").red().bold(),
|
.map_err(BasePathDiscoveryError::IoError)?;
|
||||||
target_inner
|
let mut decompressed_bytes = vec![];
|
||||||
);
|
|
||||||
|
|
||||||
println!("{}: {}", style("HINT").yellow(), style("Perhaps try providing a path to self-compiled target with the `--base` flag").italic());
|
// This errors, so idk what decoder to use
|
||||||
|
DeflateDecoder::new(compressed_reader.as_ref())
|
||||||
return None;
|
.read_to_end(&mut decompressed_bytes)
|
||||||
}
|
.await
|
||||||
|
.map_err(BasePathDiscoveryError::Decompression)?;
|
||||||
resp
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fs::OpenOptions::new()
|
fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
|
@ -185,10 +232,10 @@ async fn get_base_exe_path(
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(&path)
|
.open(&path)
|
||||||
.await
|
.await
|
||||||
.ok()?
|
.map_err(BasePathDiscoveryError::IoError)?
|
||||||
.write_all(&dl_req.bytes().await.ok()?)
|
.write_all(&decompressed_bytes)
|
||||||
.await
|
.await
|
||||||
.ok()?;
|
.map_err(BasePathDiscoveryError::IoError)?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
" {} {}",
|
" {} {}",
|
||||||
|
@ -197,8 +244,8 @@ async fn get_base_exe_path(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(path)
|
Ok(path)
|
||||||
} else {
|
} else {
|
||||||
None
|
Err(BasePathDiscoveryError::<()>::None.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue