use std::borrow::Cow; use std::path::Path; use serde::Deserialize; use serde::Serialize; use sha2::Digest; use sha2::Sha256; use crate::error::CustomError; use super::Config; #[derive(Debug, Deserialize, Serialize, Default)] pub(crate) struct TargetConfig { pub(super) name: String, pub(super) repo: String, #[serde(default)] pub(super) branch: Option, #[serde(default)] pub(super) revision: Option, #[serde(default)] pub(super) path: Option, #[serde(default)] pub(super) attr: String, #[serde(default)] pub(super) update: Option, #[serde(default)] pub(super) update_branch: Option, } impl TargetConfig { /// The folder that contains the folders for the build targets. pub(crate) fn get_target_root_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let output_directory = config_root.get_output_directory()?; Ok(Cow::Owned(output_directory.join("target"))) } /// The root directory for this specific build target. pub(crate) fn get_target_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let target_root = self.get_target_root_directory(config_root)?; Ok(Cow::Owned(target_root.join(&self.name))) } /// The folder that contains the folders containing the checkouts of the git repositories. pub(crate) fn get_repo_root_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let output_directory = config_root.get_output_directory()?; Ok(Cow::Owned(output_directory.join("repo"))) } /// The root of the checkout of the git repository. pub(crate) fn get_repo_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let hashed_repo = Sha256::digest(&self.repo); let hashed_repo = hex_string(&hashed_repo); let repo_root = self.get_repo_root_directory(config_root)?; Ok(Cow::Owned(repo_root.join(hashed_repo))) } /// The directory that contains flake.nix. pub(crate) fn get_flake_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let repo_directory = self.get_repo_directory(config_root)?; let subpath = self.path.as_deref(); if let Some(subpath) = subpath { Ok(Cow::Owned(repo_directory.join(subpath))) } else { Ok(repo_directory) } } /// The URL to the upstream git repository. pub(crate) fn get_repo(&'_ self) -> Result<&String, CustomError> { Ok(&self.repo) } /// The git branch name to track. pub(crate) fn get_branch(&'_ self) -> Result, CustomError> { if let Some(b) = &self.branch { Ok(Cow::Borrowed(b)) } else { Ok(Cow::Borrowed("main")) } } /// If we want to pin to a specific revision, this is the reference to that commit. pub(crate) fn get_revision(&self) -> Result<&Option, CustomError> { Ok(&self.revision) } /// The folder where nixos-rebuild is invoked and the outputs are linked. pub(crate) fn get_build_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let target_directory = self.get_target_directory(config_root)?; Ok(Cow::Owned(target_directory.join("build"))) } /// The flake output attribute to build (the part after '#' in the build command). pub(crate) fn get_attr(&'_ self) -> Result<&String, CustomError> { Ok(&self.attr) } } fn hex_string(data: &[u8]) -> String { let mut out = String::with_capacity(data.len() * 2); for byte in data { out.push_str(format!("{:02x}", byte).as_str()); } out }