use std::{collections::BTreeMap, fs};
use axoasset::LocalAsset;
use axoprocess::Cmd;
use camino::Utf8PathBuf;
use serde::Serialize;
use temp_dir::TempDir;
use tracing::info;
use crate::{create_tmp, DistResult};
use super::ExecutableZipFragment;
#[derive(Debug, Clone, Serialize)]
pub struct PkgInstallerInfo {
pub artifact: ExecutableZipFragment,
pub identifier: String,
pub install_location: String,
pub file_path: Utf8PathBuf,
pub package_dir: Utf8PathBuf,
pub version: String,
pub bin_aliases: BTreeMap<String, Vec<String>>,
}
impl PkgInstallerInfo {
pub fn build(&self) -> DistResult<()> {
info!("building a pkg: {}", self.identifier);
let (_build_dir, build_dir) = create_tmp()?;
let bindir = build_dir.join("bin");
LocalAsset::create_dir_all(&bindir)?;
let libdir = build_dir.join("lib");
LocalAsset::create_dir_all(&libdir)?;
info!("Copying executables");
for exe in &self.artifact.executables {
info!("{} => {:?}", &self.package_dir.join(exe), bindir.join(exe));
LocalAsset::copy_file_to_file(self.package_dir.join(exe), bindir.join(exe))?;
}
#[cfg(unix)]
for (bin, targets) in &self.bin_aliases {
for target in targets {
std::os::unix::fs::symlink(bindir.join(bin), bindir.join(target))?;
}
}
for lib in self
.artifact
.cdylibs
.iter()
.chain(self.artifact.cstaticlibs.iter())
{
LocalAsset::copy_file_to_file(self.package_dir.join(lib), libdir.join(lib))?;
}
let pkg_output = TempDir::new()?;
let pkg_output_path = pkg_output.path();
let pkg_path = pkg_output_path.join("package.pkg");
let product_path = pkg_output_path.join("product.pkg");
let mut pkgcmd = Cmd::new("/usr/bin/pkgbuild", "create individual pkg");
pkgcmd.arg("--root").arg(build_dir);
pkgcmd.arg("--identifier").arg(&self.identifier);
pkgcmd.arg("--install-location").arg(&self.install_location);
pkgcmd.arg("--version").arg(&self.version);
pkgcmd.arg(&pkg_path);
pkgcmd.stdout_to_stderr();
pkgcmd.run()?;
let mut productcmd = Cmd::new("/usr/bin/productbuild", "create final product .pkg");
productcmd.arg("--package").arg(&pkg_path);
productcmd.arg(&product_path);
productcmd.stdout_to_stderr();
productcmd.run()?;
fs::copy(&product_path, &self.file_path)?;
Ok(())
}
}