redox/src/cook/package.rs
2025-11-07 10:40:04 -07:00

108 lines
3.0 KiB
Rust

use std::{collections::BTreeSet, path::Path};
use pkg::{Package, PackageName};
use crate::{
cook::{fs::*, pty::PtyOut},
log_to_pty,
recipe::{BuildKind, Recipe},
};
pub fn package(
stage_dir: &Path,
target_dir: &Path,
name: &PackageName,
recipe: &Recipe,
auto_deps: &BTreeSet<PackageName>,
logger: &PtyOut,
) -> Result<(), String> {
if recipe.build.kind == BuildKind::None {
// metapackages don't have stage dir
package_toml(target_dir, name, recipe, auto_deps)?;
return Ok(());
}
let secret_path = "build/id_ed25519.toml";
let public_path = "build/id_ed25519.pub.toml";
if !Path::new(secret_path).is_file() || !Path::new(public_path).is_file() {
if !Path::new("build").is_dir() {
create_dir(Path::new("build"))?;
}
let (public_key, secret_key) = pkgar_keys::SecretKeyFile::new();
public_key
.save(public_path)
.map_err(|err| format!("failed to save pkgar public key: {:?}", err))?;
secret_key
.save(secret_path)
.map_err(|err| format!("failed to save pkgar secret key: {:?}", err))?;
}
let package_file = target_dir.join("stage.pkgar");
let package_meta = target_dir.join("stage.toml");
// Rebuild package if stage is newer
//TODO: rebuild on recipe changes
if package_file.is_file() {
let stage_modified = modified_dir(stage_dir)?;
if modified(&package_file)? < stage_modified {
log_to_pty!(logger, "DEBUG: updating '{}'", package_file.display());
remove_all(&package_file)?;
remove_all(&package_meta)?;
}
}
if !package_file.is_file() {
pkgar::create(
secret_path,
package_file.to_str().unwrap(),
stage_dir.to_str().unwrap(),
)
.map_err(|err| format!("failed to create pkgar archive: {:?}", err))?;
}
if !package_meta.is_file() {
package_toml(target_dir, name, recipe, auto_deps)?;
}
Ok(())
}
pub fn package_toml(
target_dir: &Path,
name: &PackageName,
recipe: &Recipe,
auto_deps: &BTreeSet<PackageName>,
) -> Result<(), String> {
let mut depends = recipe.package.dependencies.clone();
for dep in auto_deps.iter() {
if !depends.contains(dep) {
depends.push(dep.clone());
}
}
let package = Package {
name: name.clone(),
version: package_version(recipe),
target: redoxer::target().to_string(),
depends,
};
let toml_path = &target_dir.join("stage.toml");
serialize_and_write(&toml_path, &package)?;
return Ok(());
}
fn package_version(recipe: &Recipe) -> String {
if recipe.build.kind == BuildKind::None {
"".into()
} else if let Some(v) = &recipe.package.version {
v.to_string()
} else if let Some(r) = &recipe.source {
if let Some(m) = r.guess_version() {
m
} else {
"TODO".into()
}
} else {
"TODO".into()
}
}