diff --git a/backend/src/s9pk/builder.rs b/backend/src/s9pk/builder.rs index 8262a9c75..d144d2320 100644 --- a/backend/src/s9pk/builder.rs +++ b/backend/src/s9pk/builder.rs @@ -20,6 +20,7 @@ pub struct S9pkPacker< RIcon: Read, RDockerImages: Read, RAssets: Read, + RScripts: Read, > { writer: W, manifest: &'a Manifest, @@ -28,6 +29,7 @@ pub struct S9pkPacker< icon: RIcon, docker_images: RDockerImages, assets: RAssets, + scripts: RScripts, } impl< 'a, @@ -37,7 +39,8 @@ impl< RIcon: Read, RDockerImages: Read, RAssets: Read, - > S9pkPacker<'a, W, RLicense, RInstructions, RIcon, RDockerImages, RAssets> + RScripts: Read, + > S9pkPacker<'a, W, RLicense, RInstructions, RIcon, RDockerImages, RAssets, RScripts> { /// BLOCKING #[instrument(skip(self))] @@ -114,6 +117,15 @@ impl< length: new_pos - position, }; position = new_pos; + // scripts + std::io::copy(&mut self.scripts, &mut writer) + .with_ctx(|_| (crate::ErrorKind::Filesystem, "Copying Scripts"))?; + let new_pos = writer.inner_mut().stream_position()?; + header.table_of_contents.scripts = FileSection { + position, + length: new_pos - position, + }; + position = new_pos; // header let (hash, _) = writer.finish(); diff --git a/backend/src/s9pk/header.rs b/backend/src/s9pk/header.rs index 4d6011d47..3a3eb927c 100644 --- a/backend/src/s9pk/header.rs +++ b/backend/src/s9pk/header.rs @@ -38,7 +38,7 @@ impl Header { reader.read_exact(&mut magic).await?; if magic != MAGIC { return Err(Error::new( - eyre!("Incorrect Magic"), + eyre!("Incorrect Magic: {:?}", magic), crate::ErrorKind::ParseS9pk, )); } @@ -46,7 +46,7 @@ impl Header { reader.read_exact(&mut version).await?; if version[0] != VERSION { return Err(Error::new( - eyre!("Unknown Version"), + eyre!("Unknown Version: {}", version[0]), crate::ErrorKind::ParseS9pk, )); } @@ -75,6 +75,7 @@ pub struct TableOfContents { pub icon: FileSection, pub docker_images: FileSection, pub assets: FileSection, + pub scripts: FileSection, } impl TableOfContents { pub fn serialize(&self, mut writer: W) -> std::io::Result<()> { @@ -93,6 +94,7 @@ impl TableOfContents { self.docker_images .serialize_entry("docker_images", &mut writer)?; self.assets.serialize_entry("assets", &mut writer)?; + self.scripts.serialize_entry("scripts", &mut writer)?; Ok(()) } pub async fn deserialize(mut reader: R) -> std::io::Result { @@ -131,6 +133,7 @@ impl TableOfContents { icon: from_table(&table, "icon")?, docker_images: from_table(&table, "docker_images")?, assets: from_table(&table, "assets")?, + scripts: from_table(&table, "scripts")?, }) } } diff --git a/backend/src/s9pk/manifest.rs b/backend/src/s9pk/manifest.rs index 76a190a91..fba540939 100644 --- a/backend/src/s9pk/manifest.rs +++ b/backend/src/s9pk/manifest.rs @@ -166,6 +166,8 @@ pub struct Assets { pub docker_images: Option, #[serde(default)] pub assets: Option, + #[serde(default)] + pub scripts: Option, } impl Assets { pub fn license_path(&self) -> &Path { @@ -205,6 +207,12 @@ impl Assets { .map(|a| a.as_path()) .unwrap_or(Path::new("assets")) } + pub fn scripts_path(&self) -> &Path { + self.scripts + .as_ref() + .map(|a| a.as_path()) + .unwrap_or(Path::new("scripts")) + } } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/backend/src/s9pk/mod.rs b/backend/src/s9pk/mod.rs index 94e1f0666..694ebafd3 100644 --- a/backend/src/s9pk/mod.rs +++ b/backend/src/s9pk/mod.rs @@ -105,6 +105,23 @@ pub fn pack(#[context] ctx: SdkContext, #[arg] path: Option) -> Result< std::io::Cursor::new(assets.into_inner()?) }) + .scripts({ + let mut scripts = tar::Builder::new(Vec::new()); + + for (script_volume, _) in manifest + .volumes + .iter() + .filter(|(_, v)| matches!(v, &&Volume::Scripts {})) + { + scripts.append_dir_all( + script_volume, + path.join(manifest.assets.scripts_path()) + .join(script_volume), + )?; + } + + std::io::Cursor::new(scripts.into_inner()?) + }) .build() .pack(&ctx.developer_key()?)?; outfile.sync_all()?; diff --git a/backend/src/volume.rs b/backend/src/volume.rs index df78da177..38a234bdc 100644 --- a/backend/src/volume.rs +++ b/backend/src/volume.rs @@ -162,6 +162,15 @@ pub fn asset_dir>(datadir: P, pkg_id: &PackageId, version: &Versi .join(version.as_str()) } +pub fn script_dir>(datadir: P, pkg_id: &PackageId, version: &Version) -> PathBuf { + datadir + .as_ref() + .join(PKG_VOLUME_DIR) + .join(pkg_id) + .join("scripts") + .join(version.as_str()) +} + pub fn backup_dir(pkg_id: &PackageId) -> PathBuf { Path::new(BACKUP_DIR).join(pkg_id).join("data") } @@ -178,6 +187,8 @@ pub enum Volume { #[serde(rename_all = "kebab-case")] Assets {}, #[serde(rename_all = "kebab-case")] + Scripts {}, + #[serde(rename_all = "kebab-case")] Pointer { package_id: PackageId, volume_id: VolumeId, @@ -228,6 +239,7 @@ impl Volume { match self { Volume::Data { .. } => data_dir(&ctx.datadir, pkg_id, volume_id), Volume::Assets {} => asset_dir(&ctx.datadir, pkg_id, version).join(volume_id), + Volume::Scripts {} => script_dir(&ctx.datadir, pkg_id, version).join(volume_id), Volume::Pointer { package_id, volume_id, @@ -260,6 +272,7 @@ impl Volume { match self { Volume::Data { readonly } => *readonly, Volume::Assets {} => true, + Volume::Scripts {} => true, Volume::Pointer { readonly, .. } => *readonly, Volume::Certificate { .. } => true, Volume::Backup { readonly } => *readonly,