use std::path::{Path, PathBuf}; use cuddle_actions_api::ExecutableActions; use cuddle_rust_actions::RustActionsBuilder; use cuddle_value::Value; pub struct Actions { variants: Vec, } impl Actions { pub async fn new(path: &Path, value: &Value) -> anyhow::Result> { let Some(project) = value.get(&["project", "actions"]) else { tracing::debug!("found no actions folder"); return Ok(None); }; let mut variants = Vec::default(); if let Some(Value::Bool(true)) = project.get(&["rust"]) { tracing::debug!("rust actions enabled"); variants.push(ActionVariant::Rust { root_path: path.to_path_buf(), }); } else { tracing::trace!("rust actions not enabled"); } Ok(Some(Self { variants })) } pub async fn build(&mut self) -> anyhow::Result { let mut executable_actions = Vec::default(); self.clean_cache().await?; for variant in &mut self.variants { match variant { ActionVariant::Rust { root_path } => { let actions = RustActionsBuilder::new(root_path.clone()).build().await?; executable_actions.push(actions); } ActionVariant::Docker => todo!(), } } let mut exec_actions = ExecutableActions::default(); for mut actions in executable_actions { exec_actions.actions.append(&mut actions.actions); } Ok(exec_actions) } fn global_registry(&self) -> anyhow::Result> { if let Some(dir) = dirs::cache_dir().map(|c| c.join("sh.cuddle/registry/actions/rust")) { if !dir.exists() { std::fs::create_dir_all(&dir)?; } Ok(Some(dir)) } else { Ok(None) } } /// clean_cache checks whether a given function has been used in the last month, if it hasn't it is automatically removed, and potentially reconstructed again on demand pub async fn clean_cache(&mut self) -> anyhow::Result<()> { let now = std::time::SystemTime::now(); let mut file_stream = tokio::fs::read_dir( self.global_registry()? .ok_or(anyhow::anyhow!("failed to get global registry"))?, ) .await?; while let Ok(Some(entry)) = file_stream.next_entry().await { tracing::trace!("checking file: {}", entry.path().display()); let metadata = entry.metadata().await?; if metadata.is_dir() { let modified = metadata.modified()?; let cache_threshold = now .checked_sub(std::time::Duration::from_secs(60 * 24 * 30)) // Cache duration is a month .expect("to be able to have a systemtime above a week"); if modified < cache_threshold { tracing::debug!("cleaning up entry: {}", entry.path().display()); tokio::fs::remove_dir_all(entry.path()).await?; } } } Ok(()) } } pub enum ActionVariant { Rust { root_path: PathBuf }, Docker, }