diff --git a/Cargo.toml b/Cargo.toml index 066cf29..992a862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,16 +1,18 @@ [package] -name = "{{project-name}}" +name = "tci" version = "0.1.0" edition = "2021" authors = [ "alemi " ] readme = "README.md" -#description = "" -#keywords = [] +description = "tiny custom CI runner for your selfhosted just-git repositories" +keywords = ["git", "ci", "workflows", "minimal", "selfhosted"] +repository = "https://git.alemi.dev/tci.git" #documentation = "" -#repository = "https://git.alemi.dev/{{project-name}}" #license = "LICENSE" [dependencies] +git2 = "0.18.2" +tempdir = "0.3.7" [dev-dependencies] diff --git a/src/main.rs b/src/main.rs index d2b475e..828b059 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,58 @@ +use git2::{Config, Repository}; fn main() { - println!("Hello, world!"); + // println!("{:?}", std::env::args()); + // println!("{}", std::env::current_dir().unwrap().display()); + // for (key, value) in std::env::vars() { + // println!("{key}: \t{value}"); + // } + + let callback = std::path::Path::new(&std::env::args().next().expect("no argv0??")) + .file_name() + .expect("path terminates with '...'") + .to_str() + .expect("could not represent OsStr") + .to_string(); + + let repo_path = std::env::current_dir() + .expect("not in a directory???"); + + let repo_name = repo_path + .parent() + .expect("in root???") + .file_name() + .expect("path terminates with '...'") + .to_str() + .expect("could not represent OsStr") + .to_string(); + + // check config before even creating temp dir and cloning repo + let cfg = Config::open(&repo_path.join("config")).expect("could not read git config"); + let Ok(true) = cfg.get_bool("tci.allow") else { + std::process::exit(0); + }; + + let tmp = tempdir::TempDir::new(&format!("tci-{repo_name}")).expect("could not create tempdir"); + + let repo = Repository::clone(repo_path.to_str().unwrap(), tmp.path()).expect("could not clone repository"); + std::env::set_current_dir(tmp.path()).expect("could not change directory"); + + println!("[+] running tci hook [{callback}] for repo '{repo_name}'"); + let tci_script = cfg.get_str("tci.script").unwrap_or(".tci").to_string(); + + if !tmp.path().join(&tci_script).is_file() { + println!("[?] tci enabled for repo, but no .tci script found"); + std::process::exit(1); + } + + let output = std::process::Command::new(tmp.path().join(&tci_script)).output().expect("could not run tci script"); + + match std::str::from_utf8(&output.stdout) { + Ok(s) => println!("{s}"), + Err(e) => { + println!("[?] script produced non-utf8 output ({e}), showing as bytes"); + println!("{:?}", output.stdout); + }, + } + }