use crate::{cfg::TciConfig, error::{TciErr, TciResult}, git::TciRepo}; pub struct Tci { cfg: TciConfig, repo: TciRepo, // stdin: String, } impl Tci { pub fn new() -> TciResult { let cfg = TciConfig::load() .unwrap_or_else(|e| { eprintln!("[!] invalid config: {e}"); TciConfig::default() }); let repo = TciRepo::new()?; Ok(Tci{cfg, repo}) } /// check if tci is allowed to run for this repository pub fn allowed(&self) -> bool { if !self.cfg.allow_all && !self.repo.cfg.get_bool("tci.allow").unwrap_or(false) { return false; // we are in whitelist mode and this repo is not whitelisted } match self.cfg.branch.as_deref() { None => self.repo.updated("tci"), Some("") => true, Some(b) => self.repo.updated(b), } } pub fn run(&self) -> TciResult<()> { // run hooks for hook in &self.cfg.hooks { println!("[-] running hook ({hook})"); Tci::exec(&self.repo.path, hook)?; } if !self.allowed() { return Ok(()) } let env = self.prepare_env()?; let tci_script = self.repo.cfg.get_string("tci.script") .unwrap_or_else(|_| ".tci".into()); let tci_path = env.path().join(tci_script); if !tci_path.is_file() { return Err(TciErr::Missing); } println!("[+] running tci script for {}", self.repo.name); Tci::exec(env.path(), tci_path)?; println!("[o] tci complete"); Ok(()) } fn prepare_env(&self) -> TciResult { let tmp = tempdir::TempDir::new( &format!("tci-{}", self.repo.name.replace('/', "_")) )?; // TODO allow customizing clone? just clone recursive? just let hook setup submodules? git2::Repository::clone( self.repo.path.to_str() .ok_or(TciErr::FsError("repo path is not a valid string"))?, tmp.path(), )?; Ok(tmp) } fn exec>(cwd: &std::path::Path, s: S) -> TciResult<()> { match std::process::Command::new(s) .current_dir(cwd) // .stdin(self.stdin.clone()) // TODO not this easy .status()? .code() { Some(0) => Ok(()), Some(x) => Err(crate::error::TciErr::SubprocessError(x)), None => Err(crate::error::TciErr::SubprocessTerminated), } } #[allow(unused)] fn spawn>(cwd: &std::path::Path, s: S) -> TciResult { Ok( std::process::Command::new(s) .current_dir(cwd) // .stdin(self.stdin.clone()) // TODO not this easy .spawn()? ) } }