use crate::ReleaseArgs;
use crate::copy::{copy_dir_recursive, prepare_release_dir};
use crate::nar::create_nar;
use crate::update_files::generate_update_files;
use std::io;
pub fn execute_release(args: &ReleaseArgs) -> io::Result<()> {
println!("[1/5] Preparing release folder...");
prepare_release_dir(&args.release)?;
println!("[2/5] Copying target files...");
let count = copy_dir_recursive(&args.target, &args.release)?;
println!(" Copied {count} files from {}", args.target.display());
if !args.copy_dirs.is_empty() {
println!("[3/5] Applying overlay copies...");
for copy_dir in &args.copy_dirs {
let c = copy_dir_recursive(copy_dir, &args.release)?;
println!(" Copied {c} files from {}", copy_dir.display());
}
} else {
println!("[3/5] Applying overlay copies... (none specified)");
}
println!("[4/5] Generating update files...");
let entries = generate_update_files(&args.release)?;
println!(" Generated updates.txt ({entries} entries)");
println!("[5/5] Creating NAR archive...");
let nar_size = create_nar(&args.release, &args.nar)?;
let nar_size_kb = nar_size as f64 / 1024.0;
println!(" Created {} ({nar_size_kb:.1} KB)", args.nar.display());
println!();
println!("Release complete!");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_execute_release_full_pipeline() {
let temp = TempDir::new().unwrap();
let target = temp.path().join("target_ghost");
fs::create_dir_all(target.join("ghost/master")).unwrap();
fs::write(target.join("ghost/master/descript.txt"), "desc").unwrap();
fs::write(target.join("install.txt"), "install").unwrap();
let release = temp.path().join("release_out");
let nar = temp.path().join("out.nar");
let args = ReleaseArgs {
target: target.clone(),
release: release.clone(),
nar: nar.clone(),
copy_dirs: vec![],
};
execute_release(&args).unwrap();
assert!(!release.join("updates2.dau").exists());
assert!(release.join("updates.txt").exists());
assert!(nar.exists());
assert!(nar.metadata().unwrap().len() > 0);
assert!(!target.join("updates2.dau").exists());
assert_eq!(
fs::read_to_string(target.join("install.txt")).unwrap(),
"install"
);
}
#[test]
fn test_execute_release_with_copy() {
let temp = TempDir::new().unwrap();
let target = temp.path().join("target_ghost");
fs::create_dir_all(&target).unwrap();
fs::write(target.join("a.txt"), "original").unwrap();
let overlay = temp.path().join("overlay");
fs::create_dir_all(&overlay).unwrap();
fs::write(overlay.join("a.txt"), "overwritten").unwrap();
fs::write(overlay.join("b.txt"), "new file").unwrap();
let release = temp.path().join("release_out");
let nar = temp.path().join("out.nar");
let args = ReleaseArgs {
target: target.clone(),
release: release.clone(),
nar,
copy_dirs: vec![overlay],
};
execute_release(&args).unwrap();
assert_eq!(
fs::read_to_string(release.join("a.txt")).unwrap(),
"overwritten"
);
assert_eq!(
fs::read_to_string(release.join("b.txt")).unwrap(),
"new file"
);
assert_eq!(
fs::read_to_string(target.join("a.txt")).unwrap(),
"original"
);
}
}