mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 14:29:45 +00:00
Refactor/project structure (#3085)
* refactor project structure * environment-based default registry * fix tests * update build container * use docker platform for iso build emulation * simplify compat * Fix docker platform spec in run-compat.sh * handle riscv compat * fix bug with dep error exists attr * undo removal of sorting * use qemu for iso stage --------- Co-authored-by: Mariusz Kogen <k0gen@pm.me> Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
213
core/src/registry/os/asset/get.rs
Normal file
213
core/src/registry/os/asset/get.rs
Normal file
@@ -0,0 +1,213 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::panic::UnwindSafe;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use clap::Parser;
|
||||
use exver::Version;
|
||||
use imbl_value::{InternedString, json};
|
||||
use itertools::Itertools;
|
||||
use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::context::CliContext;
|
||||
use crate::prelude::*;
|
||||
use crate::progress::{FullProgressTracker, ProgressUnits};
|
||||
use crate::registry::asset::RegistryAsset;
|
||||
use crate::registry::context::RegistryContext;
|
||||
use crate::registry::os::SIG_CONTEXT;
|
||||
use crate::registry::os::index::OsVersionInfo;
|
||||
use crate::s9pk::merkle_archive::source::multi_cursor_file::MultiCursorFile;
|
||||
use crate::sign::commitment::Commitment;
|
||||
use crate::sign::commitment::blake3::Blake3Commitment;
|
||||
use crate::util::io::{AtomicFile, open_file};
|
||||
|
||||
pub fn get_api<C: Context>() -> ParentHandler<C> {
|
||||
ParentHandler::new()
|
||||
.subcommand(
|
||||
"iso",
|
||||
from_fn_async(get_iso)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.no_cli(),
|
||||
)
|
||||
.subcommand(
|
||||
"iso",
|
||||
from_fn_async(cli_get_os_asset)
|
||||
.no_display()
|
||||
.with_about("Download iso"),
|
||||
)
|
||||
.subcommand(
|
||||
"img",
|
||||
from_fn_async(get_img)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.no_cli(),
|
||||
)
|
||||
.subcommand(
|
||||
"img",
|
||||
from_fn_async(cli_get_os_asset)
|
||||
.no_display()
|
||||
.with_about("Download img"),
|
||||
)
|
||||
.subcommand(
|
||||
"squashfs",
|
||||
from_fn_async(get_squashfs)
|
||||
.with_metadata("authenticated", Value::Bool(false))
|
||||
.no_cli(),
|
||||
)
|
||||
.subcommand(
|
||||
"squashfs",
|
||||
from_fn_async(cli_get_os_asset)
|
||||
.no_display()
|
||||
.with_about("Download squashfs"),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
pub struct GetOsAssetParams {
|
||||
#[ts(type = "string")]
|
||||
pub version: Version,
|
||||
#[ts(type = "string")]
|
||||
pub platform: InternedString,
|
||||
}
|
||||
|
||||
async fn get_os_asset(
|
||||
ctx: RegistryContext,
|
||||
GetOsAssetParams { version, platform }: GetOsAssetParams,
|
||||
accessor: impl FnOnce(
|
||||
&Model<OsVersionInfo>,
|
||||
) -> &Model<BTreeMap<InternedString, RegistryAsset<Blake3Commitment>>>
|
||||
+ UnwindSafe
|
||||
+ Send,
|
||||
) -> Result<RegistryAsset<Blake3Commitment>, Error> {
|
||||
accessor(
|
||||
ctx.db
|
||||
.peek()
|
||||
.await
|
||||
.as_index()
|
||||
.as_os()
|
||||
.as_versions()
|
||||
.as_idx(&version)
|
||||
.or_not_found(&version)?,
|
||||
)
|
||||
.as_idx(&platform)
|
||||
.or_not_found(&platform)?
|
||||
.de()
|
||||
}
|
||||
|
||||
pub async fn get_iso(
|
||||
ctx: RegistryContext,
|
||||
params: GetOsAssetParams,
|
||||
) -> Result<RegistryAsset<Blake3Commitment>, Error> {
|
||||
get_os_asset(ctx, params, |info| info.as_iso()).await
|
||||
}
|
||||
|
||||
pub async fn get_img(
|
||||
ctx: RegistryContext,
|
||||
params: GetOsAssetParams,
|
||||
) -> Result<RegistryAsset<Blake3Commitment>, Error> {
|
||||
get_os_asset(ctx, params, |info| info.as_img()).await
|
||||
}
|
||||
|
||||
pub async fn get_squashfs(
|
||||
ctx: RegistryContext,
|
||||
params: GetOsAssetParams,
|
||||
) -> Result<RegistryAsset<Blake3Commitment>, Error> {
|
||||
get_os_asset(ctx, params, |info| info.as_squashfs()).await
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Parser)]
|
||||
#[command(rename_all = "kebab-case")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliGetOsAssetParams {
|
||||
pub version: Version,
|
||||
pub platform: InternedString,
|
||||
#[arg(
|
||||
long = "download",
|
||||
short = 'd',
|
||||
help = "The path of the directory to download to"
|
||||
)]
|
||||
pub download: Option<PathBuf>,
|
||||
#[arg(
|
||||
long = "reverify",
|
||||
short = 'r',
|
||||
help = "verify the hash of the file a second time after download"
|
||||
)]
|
||||
pub reverify: bool,
|
||||
}
|
||||
|
||||
async fn cli_get_os_asset(
|
||||
HandlerArgs {
|
||||
context: ctx,
|
||||
parent_method,
|
||||
method,
|
||||
params:
|
||||
CliGetOsAssetParams {
|
||||
version,
|
||||
platform,
|
||||
download,
|
||||
reverify,
|
||||
},
|
||||
..
|
||||
}: HandlerArgs<CliContext, CliGetOsAssetParams>,
|
||||
) -> Result<RegistryAsset<Blake3Commitment>, Error> {
|
||||
let ext = method
|
||||
.iter()
|
||||
.last()
|
||||
.or_else(|| parent_method.iter().last())
|
||||
.unwrap_or(&"bin");
|
||||
|
||||
let res = from_value::<RegistryAsset<Blake3Commitment>>(
|
||||
ctx.call_remote::<RegistryContext>(
|
||||
&parent_method.iter().chain(&method).join("."),
|
||||
json!({
|
||||
"version": version,
|
||||
"platform": platform,
|
||||
}),
|
||||
)
|
||||
.await?,
|
||||
)?;
|
||||
|
||||
res.validate(SIG_CONTEXT, res.all_signers())?;
|
||||
|
||||
if let Some(download) = download {
|
||||
let download = download.join(format!("startos-{version}_{platform}.{ext}"));
|
||||
let mut file = AtomicFile::new(&download, None::<&Path>).await?;
|
||||
|
||||
let progress = FullProgressTracker::new();
|
||||
let mut download_phase =
|
||||
progress.add_phase(InternedString::intern("Downloading File"), Some(100));
|
||||
download_phase.set_total(res.commitment.size);
|
||||
download_phase.set_units(Some(ProgressUnits::Bytes));
|
||||
let reverify_phase = if reverify {
|
||||
Some(progress.add_phase(InternedString::intern("Reverifying File"), Some(10)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let progress_task = progress.progress_bar_task("Downloading...");
|
||||
|
||||
download_phase.start();
|
||||
let mut download_writer = download_phase.writer(&mut *file);
|
||||
res.download(ctx.client.clone(), &mut download_writer)
|
||||
.await?;
|
||||
let (_, mut download_phase) = download_writer.into_inner();
|
||||
file.save().await?;
|
||||
download_phase.complete();
|
||||
|
||||
if let Some(mut reverify_phase) = reverify_phase {
|
||||
reverify_phase.start();
|
||||
res.commitment
|
||||
.check(&MultiCursorFile::from(open_file(download).await?))
|
||||
.await?;
|
||||
reverify_phase.complete();
|
||||
}
|
||||
|
||||
progress.complete();
|
||||
|
||||
progress_task.await.with_kind(ErrorKind::Unknown)?;
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
Reference in New Issue
Block a user