mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
rename frontend to web and update contributing guide (#2509)
* rename frontend to web and update contributing guide * rename this time * fix build * restructure rust code * update documentation * update descriptions * Update CONTRIBUTING.md Co-authored-by: J H <2364004+Blu-J@users.noreply.github.com> --------- Co-authored-by: Aiden McClelland <me@drbonez.dev> Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com> Co-authored-by: J H <2364004+Blu-J@users.noreply.github.com>
This commit is contained in:
145
core/startos/src/s9pk/builder.rs
Normal file
145
core/startos/src/s9pk/builder.rs
Normal file
@@ -0,0 +1,145 @@
|
||||
use sha2::{Digest, Sha512};
|
||||
use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom};
|
||||
use tracing::instrument;
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
use super::header::{FileSection, Header};
|
||||
use super::manifest::Manifest;
|
||||
use super::SIG_CONTEXT;
|
||||
use crate::util::io::to_cbor_async_writer;
|
||||
use crate::util::HashWriter;
|
||||
use crate::{Error, ResultExt};
|
||||
|
||||
#[derive(TypedBuilder)]
|
||||
pub struct S9pkPacker<
|
||||
'a,
|
||||
W: AsyncWriteExt + AsyncSeekExt,
|
||||
RLicense: AsyncReadExt + Unpin,
|
||||
RInstructions: AsyncReadExt + Unpin,
|
||||
RIcon: AsyncReadExt + Unpin,
|
||||
RDockerImages: AsyncReadExt + Unpin,
|
||||
RAssets: AsyncReadExt + Unpin,
|
||||
RScripts: AsyncReadExt + Unpin,
|
||||
> {
|
||||
writer: W,
|
||||
manifest: &'a Manifest,
|
||||
license: RLicense,
|
||||
instructions: RInstructions,
|
||||
icon: RIcon,
|
||||
docker_images: RDockerImages,
|
||||
assets: RAssets,
|
||||
scripts: Option<RScripts>,
|
||||
}
|
||||
impl<
|
||||
'a,
|
||||
W: AsyncWriteExt + AsyncSeekExt + Unpin,
|
||||
RLicense: AsyncReadExt + Unpin,
|
||||
RInstructions: AsyncReadExt + Unpin,
|
||||
RIcon: AsyncReadExt + Unpin,
|
||||
RDockerImages: AsyncReadExt + Unpin,
|
||||
RAssets: AsyncReadExt + Unpin,
|
||||
RScripts: AsyncReadExt + Unpin,
|
||||
> S9pkPacker<'a, W, RLicense, RInstructions, RIcon, RDockerImages, RAssets, RScripts>
|
||||
{
|
||||
/// BLOCKING
|
||||
#[instrument(skip_all)]
|
||||
pub async fn pack(mut self, key: &ed25519_dalek::SigningKey) -> Result<(), Error> {
|
||||
let header_pos = self.writer.stream_position().await?;
|
||||
if header_pos != 0 {
|
||||
tracing::warn!("Appending to non-empty file.");
|
||||
}
|
||||
let mut header = Header::placeholder();
|
||||
header.serialize(&mut self.writer).await.with_ctx(|_| {
|
||||
(
|
||||
crate::ErrorKind::Serialization,
|
||||
"Writing Placeholder Header",
|
||||
)
|
||||
})?;
|
||||
let mut position = self.writer.stream_position().await?;
|
||||
|
||||
let mut writer = HashWriter::new(Sha512::new(), &mut self.writer);
|
||||
// manifest
|
||||
to_cbor_async_writer(&mut writer, self.manifest).await?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.manifest = FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
};
|
||||
position = new_pos;
|
||||
// license
|
||||
tokio::io::copy(&mut self.license, &mut writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying License"))?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.license = FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
};
|
||||
position = new_pos;
|
||||
// instructions
|
||||
tokio::io::copy(&mut self.instructions, &mut writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying Instructions"))?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.instructions = FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
};
|
||||
position = new_pos;
|
||||
// icon
|
||||
tokio::io::copy(&mut self.icon, &mut writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying Icon"))?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.icon = FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
};
|
||||
position = new_pos;
|
||||
// docker_images
|
||||
tokio::io::copy(&mut self.docker_images, &mut writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying Docker Images"))?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.docker_images = FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
};
|
||||
position = new_pos;
|
||||
// assets
|
||||
tokio::io::copy(&mut self.assets, &mut writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying Assets"))?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.assets = FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
};
|
||||
position = new_pos;
|
||||
// scripts
|
||||
if let Some(mut scripts) = self.scripts {
|
||||
tokio::io::copy(&mut scripts, &mut writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying Scripts"))?;
|
||||
let new_pos = writer.inner_mut().stream_position().await?;
|
||||
header.table_of_contents.scripts = Some(FileSection {
|
||||
position,
|
||||
length: new_pos - position,
|
||||
});
|
||||
position = new_pos;
|
||||
}
|
||||
|
||||
// header
|
||||
let (hash, _) = writer.finish();
|
||||
self.writer.seek(SeekFrom::Start(header_pos)).await?;
|
||||
header.pubkey = key.into();
|
||||
header.signature = key.sign_prehashed(hash, Some(SIG_CONTEXT))?;
|
||||
header
|
||||
.serialize(&mut self.writer)
|
||||
.await
|
||||
.with_ctx(|_| (crate::ErrorKind::Serialization, "Writing Header"))?;
|
||||
self.writer.seek(SeekFrom::Start(position)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user