continuous-testing 2.0.0

A continuous testing tool
use marked_yaml::parse_yaml;
use notifme::Notification;
use std::env::current_dir;
use std::fs::File;
use std::io::Write;
use std::{
    fs,
    path::Path,
    process::{exit, Command, ExitCode},
};
const HOOK: &str = ".git/hooks/post-commit";
const CONTINUOUS: &str = "continuous";
const ICON_DIR: &str = ".icons";
const RELEASE: &str = "1.0.0";
fn init_hook() -> i32 {
    let mut f = File::create(HOOK).expect("");
    f.write_all(b"#!/bin/bash\n\nunset GIT_DIR\n\nagain\n\nexit $?\n\n")
        .expect("failed to write file");
    f.sync_data().expect("failed to write file");
    assert!(Command::new("chmod")
        .arg("+x")
        .arg(HOOK)
        .current_dir(".")
        .spawn()
        .expect("chmod not founded")
        .wait()
        .expect("")
        .success());
    send(project().as_str(), "Is now tracked by continuous testing")
}
fn help(args: &[String]) -> i32 {
    println!("{}              : Run the hook", args[0]);
    println!("{} --help       : Display help", args[0]);
    println!("{} init         : Init the repository", args[0]);
    0
}

fn project() -> String {
    current_dir()
        .expect("")
        .as_path()
        .iter()
        .last()
        .expect("")
        .to_str()
        .expect("failed to get current dir")
        .to_string()
}
fn commit() -> String {
    if Path::new("commit").is_file() {
        fs::remove_file("commit").expect("failed to remove the file");
    }
    let f = File::create("commit").expect("failed to create the file");
    assert!(Command::new("git")
        .arg("log")
        .arg("-1")
        .arg("--pretty=%s")
        .stdout(f)
        .current_dir(".")
        .spawn()
        .expect("failed to get last commit")
        .wait()
        .expect("")
        .success());
    fs::read_to_string("commit").expect("failed to read the commit file")
}
fn send(summary: &str, body: &str) -> i32 {
    let icon = format!("{}/{ICON_DIR}/continuous.png", env!("HOME"));

    assert!(Notification::new()
        .app(project().as_str())
        .icon(icon.as_str())
        .summary(summary)
        .body(body)
        .send());
    0
}
fn init() -> i32 {
    if Path::new(".git").is_dir() && Path::new(HOOK).exists() {
        println!("Already initialized");
        exit(0);
    } else if !Path::new(".git").exists() {
        assert!(Command::new("git")
            .arg("init")
            .current_dir(".")
            .spawn()
            .expect("git not found")
            .wait()
            .expect("")
            .success());
    }

    let icons = format!("{}/{}", env!("HOME"), ICON_DIR);
    if !Path::new(icons.as_str()).exists() {
        fs::create_dir(icons.as_str()).expect("failed to create the icon directory");
    }

    if !Path::new(format!("{icons}/continuous.png").as_str()).exists() {
        assert!(fs::copy(
            "/tmp/continuous-testing/.icon/notif.png",
            format!("{icons}/continuous.png").as_str()
        )
        .is_ok());
    }

    assert_eq!(init_hook(), 0);
    assert_eq!(init_continuous(), 0);
    0
}

fn yaml(key: &str) -> String {
    let binding = parse_yaml(0, include_str!("../again.yaml")).unwrap();
    let k = binding.as_mapping().expect("").get(key);
    k.expect("").as_scalar().expect("").to_string()
}

fn gen_script() -> i32 {
    let dir = format!("{CONTINUOUS}/{}", yaml("language"));
    let repository = yaml("repository");
    let provider = yaml("provider");
    let username = yaml("username");
    assert!(Command::new("bash")
        .arg("scripts-gen")
        .arg(provider.as_str())
        .arg(username.as_str())
        .arg(repository.as_str())
        .current_dir(dir.as_str())
        .spawn()
        .expect("bash not found")
        .wait()
        .expect("")
        .success());
    0
}
fn init_continuous() -> i32 {
    assert!(Command::new("git")
        .arg("clone")
        .arg("--quiet")
        .arg("https://github.com/taishingi/continuous-template.git")
        .arg(".repo")
        .current_dir(".")
        .spawn()
        .expect("git no founded")
        .wait()
        .expect("")
        .success());
    assert!(Command::new("git")
        .arg("fetch")
        .arg("--all")
        .arg("--tags")
        .current_dir(".repo")
        .spawn()
        .expect("git no founded")
        .wait()
        .expect("")
        .success());
    assert!(Command::new("git")
        .arg("checkout")
        .arg("-b")
        .arg(env!("USER").to_string().as_str())
        .arg(RELEASE)
        .current_dir(".repo")
        .spawn()
        .expect("git no founded")
        .wait()
        .expect("")
        .success());

    if Path::new(CONTINUOUS).exists() {
        fs::remove_dir_all(CONTINUOUS).expect("Failed to remove the continuous directory");
    }
    assert!(Command::new("mv")
        .arg(".repo")
        .arg(CONTINUOUS)
        .current_dir(".")
        .spawn()
        .expect("failed to find mv")
        .wait()
        .expect("")
        .success());
    gen_script()
}

fn packer(dir: &str) -> i32 {
    assert!(Command::new("packer")
        .arg("validate")
        .arg(".")
        .current_dir(dir)
        .spawn()
        .expect("")
        .wait()
        .expect("")
        .success());
    assert!(Command::new("packer")
        .arg("build")
        .arg(".")
        .current_dir(dir)
        .spawn()
        .expect("")
        .wait()
        .expect("")
        .success());
    send(commit().as_str(), "All tests passes")
}
fn check() -> i32 {
    assert_eq!(push(), 0);
    if Path::new(CONTINUOUS).exists() {
        if yaml("language").as_str().eq("rust") {
            return packer(format!("./{CONTINUOUS}/rust").as_str());
        } else if yaml("language").as_str().eq("d") {
            return packer(format!("{CONTINUOUS}/d").as_str());
        } else if yaml("language").as_str().eq("go") {
            return packer(format!("{CONTINUOUS}/go").as_str());
        }
    }
    1
}

fn push() -> i32 {
    assert!(Command::new("git")
        .arg("push")
        .arg(yaml("remote").as_str())
        .arg("--all")
        .current_dir(".")
        .spawn()
        .expect("git push error")
        .wait()
        .expect("")
        .success());
    assert!(Command::new("git")
        .arg("push")
        .arg(yaml("remote").as_str())
        .arg("--tags")
        .current_dir(".")
        .spawn()
        .expect("git push error")
        .wait()
        .expect("")
        .success());
    0
}
fn main() -> ExitCode {
    let args: Vec<String> = std::env::args().collect();
    if args.len() == 2 && args.get(1).expect("").eq("init") {
        exit(init());
    } else if args.len() == 2 && args.get(1).expect("").eq("--help") {
        exit(help(&args));
    }
    exit(check());
}