Skip to content

Commit

Permalink
signing: fix pbos with only a config (#734)
Browse files Browse the repository at this point in the history
  • Loading branch information
BrettMayson authored Aug 7, 2024
1 parent aba2f74 commit 00ff748
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 6 deletions.
66 changes: 63 additions & 3 deletions bin/src/modules/sign.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use std::fs::{create_dir_all, File};
use std::{
fs::{create_dir_all, File},
sync::Arc,
};

use git2::Repository;
use hemtt_common::prefix::FILES;
use hemtt_pbo::ReadablePbo;
use hemtt_signing::BIPrivateKey;
use hemtt_workspace::addons::Location;
use hemtt_workspace::{
addons::Location,
reporting::{Code, Diagnostic},
};

use crate::{context::Context, error::Error, report::Report};

Expand All @@ -27,7 +34,32 @@ impl Module for Sign {
if ctx.config().version().git_hash().is_some() {
Repository::discover(".")?;
}
Ok(Report::new())

let mut report = Report::new();

ctx.addons().to_vec().iter().for_each(|addon| {
let entries = std::fs::read_dir(addon.folder())
.expect("valid read_dir")
.collect::<Result<Vec<_>, _>>()
.expect("files valid");
if entries.is_empty() {
report.error(EmptyAddon::code(addon.folder()));
} else if entries.len() == 1 {
// prefix files won't end up in the PBO, so we need to ignore them
if FILES.contains(
&entries[0]
.file_name()
.into_string()
.expect("valid file name")
.to_lowercase()
.as_str(),
) {
report.error(EmptyAddon::code(addon.folder()));
}
}
});

Ok(report)
}

fn pre_release(&self, ctx: &Context) -> Result<Report, Error> {
Expand Down Expand Up @@ -119,3 +151,31 @@ pub fn get_authority(ctx: &Context, suffix: Option<&str>) -> Result<String, Erro
}
Ok(authority)
}

pub struct EmptyAddon {
file: String,
}
impl Code for EmptyAddon {
fn ident(&self) -> &'static str {
"BSE1"
}

fn message(&self) -> String {
format!("Addon `{}` has no files", self.file)
}

fn note(&self) -> Option<String> {
Some("HEMTT will not be able to sign an empty PBO".to_string())
}

fn diagnostic(&self) -> Option<Diagnostic> {
Some(Diagnostic::simple(self))
}
}

impl EmptyAddon {
#[must_use]
pub fn code(file: String) -> Arc<dyn Code> {
Arc::new(Self { file })
}
}
3 changes: 3 additions & 0 deletions libs/pbo/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ pub enum Error {
#[error("File is too large for PBO format")]
/// File is too large for PBO format
FileTooLarge,
#[error("HEMTT does not support signing PBOs with no files")]
/// HEMTT does not support signing PBOs with no files
NoFiles,
}
13 changes: 10 additions & 3 deletions libs/pbo/src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ impl<I: Seek + Read> ReadablePbo<I> {
pub fn hash_filenames(&mut self) -> Result<Checksum, Error> {
let mut hasher = Sha1::new();

if self.files().is_empty() {
return Err(Error::NoFiles);
}

for header in &self.files_sorted() {
// Skip empty files
let Some(mut file) = self.file(header.filename())? else {
Expand All @@ -237,20 +241,23 @@ impl<I: Seek + Read> ReadablePbo<I> {
pub fn hash_files(&mut self, version: BISignVersion) -> Result<Checksum, Error> {
let mut hasher = Sha1::new();

if self.files().is_empty() {
hasher.update(version.nothing());
}
let mut nothing = true;

for header in &self.files_sorted() {
if !version.should_hash_file(header.filename()) {
continue;
}
nothing = false;
let Some(mut file) = self.file(header.filename())? else {
continue;
};
std::io::copy(&mut file, &mut hasher)?;
}

if nothing {
hasher.update(version.nothing());
}

Ok(hasher.finalize().to_vec().into())
}
}

0 comments on commit 00ff748

Please sign in to comment.