mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
117 lines
3.7 KiB
Rust
117 lines
3.7 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use color_eyre::eyre::eyre;
|
|
use rpc_toolkit::command;
|
|
use tracing::instrument;
|
|
|
|
use crate::context::SdkContext;
|
|
use crate::s9pk::builder::S9pkPacker;
|
|
use crate::s9pk::manifest::Manifest;
|
|
use crate::s9pk::reader::S9pkReader;
|
|
use crate::util::display_none;
|
|
use crate::volume::Volume;
|
|
use crate::{Error, ResultExt};
|
|
|
|
pub mod builder;
|
|
pub mod header;
|
|
pub mod manifest;
|
|
pub mod reader;
|
|
|
|
pub const SIG_CONTEXT: &'static [u8] = b"s9pk";
|
|
|
|
#[command(cli_only, display(display_none), blocking)]
|
|
#[instrument(skip(ctx))]
|
|
pub fn pack(#[context] ctx: SdkContext, #[arg] path: Option<PathBuf>) -> Result<(), Error> {
|
|
use std::fs::File;
|
|
use std::io::Read;
|
|
|
|
let path = if let Some(path) = path {
|
|
path
|
|
} else {
|
|
std::env::current_dir()?
|
|
};
|
|
let manifest: Manifest = if path.join("manifest.toml").exists() {
|
|
let mut s = String::new();
|
|
File::open(path.join("manifest.toml"))?.read_to_string(&mut s)?;
|
|
serde_toml::from_str(&s).with_kind(crate::ErrorKind::Deserialization)?
|
|
} else if path.join("manifest.yaml").exists() {
|
|
serde_yaml::from_reader(File::open(path.join("manifest.yaml"))?)
|
|
.with_kind(crate::ErrorKind::Deserialization)?
|
|
} else if path.join("manifest.json").exists() {
|
|
serde_json::from_reader(File::open(path.join("manifest.json"))?)
|
|
.with_kind(crate::ErrorKind::Deserialization)?
|
|
} else {
|
|
return Err(Error::new(
|
|
eyre!("manifest not found"),
|
|
crate::ErrorKind::Pack,
|
|
));
|
|
};
|
|
|
|
let outfile_path = path.join(format!("{}.s9pk", manifest.id));
|
|
let mut outfile = File::create(outfile_path)?;
|
|
S9pkPacker::builder()
|
|
.manifest(&manifest)
|
|
.writer(&mut outfile)
|
|
.license(
|
|
File::open(path.join(manifest.assets.license_path())).with_ctx(|_| {
|
|
(
|
|
crate::ErrorKind::Filesystem,
|
|
manifest.assets.license_path().display().to_string(),
|
|
)
|
|
})?,
|
|
)
|
|
.icon(
|
|
File::open(path.join(manifest.assets.icon_path())).with_ctx(|_| {
|
|
(
|
|
crate::ErrorKind::Filesystem,
|
|
manifest.assets.icon_path().display().to_string(),
|
|
)
|
|
})?,
|
|
)
|
|
.instructions(
|
|
File::open(path.join(manifest.assets.instructions_path())).with_ctx(|_| {
|
|
(
|
|
crate::ErrorKind::Filesystem,
|
|
manifest.assets.instructions_path().display().to_string(),
|
|
)
|
|
})?,
|
|
)
|
|
.docker_images(
|
|
File::open(path.join(manifest.assets.docker_images_path())).with_ctx(|_| {
|
|
(
|
|
crate::ErrorKind::Filesystem,
|
|
manifest.assets.docker_images_path().display().to_string(),
|
|
)
|
|
})?,
|
|
)
|
|
.assets({
|
|
let mut assets = tar::Builder::new(Vec::new()); // TODO: Ideally stream this? best not to buffer in memory
|
|
|
|
for (asset_volume, _) in manifest
|
|
.volumes
|
|
.iter()
|
|
.filter(|(_, v)| matches!(v, &&Volume::Assets {}))
|
|
{
|
|
assets.append_dir_all(
|
|
asset_volume,
|
|
path.join(manifest.assets.assets_path()).join(asset_volume),
|
|
)?;
|
|
}
|
|
|
|
std::io::Cursor::new(assets.into_inner()?)
|
|
})
|
|
.build()
|
|
.pack(&ctx.developer_key()?)?;
|
|
outfile.sync_all()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[command(cli_only, display(display_none))]
|
|
pub async fn verify(#[arg] path: PathBuf) -> Result<(), Error> {
|
|
let mut s9pk = S9pkReader::open(path, true).await?;
|
|
s9pk.validate().await?;
|
|
|
|
Ok(())
|
|
}
|