diff --git a/Cargo.lock b/Cargo.lock index bab985b..33b8306 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -86,6 +97,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "core-foundation" version = "0.9.3" @@ -116,8 +138,10 @@ name = "docki" version = "0.2.0" dependencies = [ "bytes", + "colored", "regex", "reqwest", + "text_io", "zip-extract", ] @@ -252,6 +276,15 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.2.6" @@ -460,7 +493,7 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] @@ -740,6 +773,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "text_io" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" + [[package]] name = "thiserror" version = "1.0.38" diff --git a/Cargo.toml b/Cargo.toml index 90a4e0a..2c277d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ license-file = "LICENSE.txt" [dependencies] bytes = "1.4.0" +colored = "2.0.0" regex = "1.7.1" reqwest = { version = "0.11.14", features = ["blocking"] } +text_io = "0.1.12" zip-extract = "0.1.1" diff --git a/src/app/commands/health.rs b/src/app/commands/health.rs new file mode 100644 index 0000000..40a7746 --- /dev/null +++ b/src/app/commands/health.rs @@ -0,0 +1,123 @@ +use std::{collections::HashMap, env, fs::File, io::Write, process}; + +use crate::app::fs_util; + +use super::traits::Command; +use bytes::Bytes; +use colored::Colorize; + +pub struct Health; + +const REVEAL_VERSION: &str ="v5.0.0-rc.1"; +const REVEAL_PATH: &str = "~/.docki/asciidoctor-reveal"; + +fn reveal_url(os: String) -> String { + return format!("https://github.com/asciidoctor/asciidoctor-reveal.js/releases/download/{}/asciidoctor-revealjs-{}", REVEAL_VERSION, os) +} + +impl Command for Health { + fn execute(&self, _args: &HashMap) -> Result<(), String> { + Self::health(); + return Ok(()) + } + + fn new() -> Self where Self: Sized { + return Self {} + } +} + + +impl Health { + + fn health() { + println!("checking required softwar ... \n"); + let asciidoctor_installed = Self::asciidoctor_is_installed(); + let asciidoctor_reveal_installed = Self::asciidoctor_revealjs_is_installed(); + + if asciidoctor_installed { + println!("- ✔️ {}", "asciidoctor".green()) + } else { + println!("- ❓{}", "asciidoctor \n".bright_red()); + Self::print_asciidoctor_install_help(); + println!(""); + } + + if asciidoctor_reveal_installed { + println!("- ✔️ {}", "asciidoctor-revealjs".green()) + } else { + println!("- ❓{}", "asciidoctor-revealjs \n".bright_red()); + Self::ask_to_install_reveal() + } + } + + fn ask_to_install_reveal() { + print!("Do you want to install it ? (y/n)"); + let user_input: String = text_io::read!("{}\n"); + + if user_input.to_lowercase() == "y" { + let os = env::consts::OS; + let url = reveal_url(os.to_string()); + println!("installing"); + let data = Self::donwload(&url).expect("failed installing"); + Self::save_to("~/.docki/asciidoctor-revealjs", data); + } else if user_input.to_lowercase() == "y"{ + println!("not installing") + } else { + println!("not a valid option (not installing)") + } + } + + fn print_asciidoctor_install_help() { + println!("you may want to install it with your package manager"); + println!(""); + println!("{}", "sudo apt install asciidoctor".yellow()); + println!("{}", "brew install asciidoctor".yellow()); + println!("{}", "sudo pacman -Syu asciidoctor".yellow()); + println!("{}", "yay -Syu asciidoctor".yellow()); + println!("{}", "dnf install asciidoctor".yellow()); + } + + fn asciidoctor_is_installed() -> bool { + return process::Command::new("asciidoctor") + .output() + .is_ok() + } + + fn asciidoctor_revealjs_is_installed() -> bool { + return process::Command::new("asciidoctor-revealjs") + .output() + .is_ok() + } + + fn donwload(url: &str) -> Result { + let Ok(response) = reqwest::blocking::get(url) else { + return Err(()); + }; + + let Ok(data) = response.bytes() else { + return Err(()); + }; + + return Ok(data) + } + + fn save_to(path: &str, data: Bytes) -> () { + let segments: &Vec<&str> = &path.split("/").collect(); + let parent_dir = &segments[0..segments.len() - 1].join("/"); + fs_util::create_dir_recursive(parent_dir); + let mut file = File::create(path).expect("failed to create file"); + file.write_all(&data).expect("failed saving file") + } +} + +#[cfg(test)] +mod test { + use std::env; + + + #[test] + fn download() { + println!("{}", env::consts::OS); + assert!(false) + } +} diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index 6d3eea7..fe09cdc 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -2,12 +2,12 @@ use std::collections::HashMap; use traits::Command; -use self::{build::Build, setup::Setup}; +use self::{build::Build, health::Health}; pub mod traits; pub mod executions; mod build; -mod setup; +mod health; pub struct CommandRegistry { commands: HashMap> @@ -18,7 +18,7 @@ impl CommandRegistry { pub fn register_all(&mut self) { let registry = self; registry.register("/build".to_string(), Box::new(Build::new()), true); - registry.register("/setup".to_string(), Box::new(Setup::new()), true); + registry.register("/health".to_string(), Box::new(Health::new()), true); } diff --git a/src/app/commands/setup.rs b/src/app/commands/setup.rs deleted file mode 100644 index fcfca35..0000000 --- a/src/app/commands/setup.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::{collections::HashMap, env, fs::File, io::Write}; - -use super::traits::Command; -use bytes::Bytes; - -pub struct Setup; - -impl Command for Setup { - fn execute(&self, _args: &HashMap) -> Result<(), String> { - Self::setup(); - return Ok(()) - } - - fn new() -> Self where Self: Sized { - return Self {} - } -} - - -impl Setup { - - fn setup() { - let os = env::consts::OS; - - let reveal_bin_url = format!("https://github.com/asciidoctor/asciidoctor-reveal.js/releases/download/v5.0.0-rc.1/asciidoctor-revealjs-{os}"); - let reveal_bin = Self::donwload(&reveal_bin_url).expect("could not download asciidoctor binary"); - let mut reveal_file = File::create("/usr/local/bin/asciidoctor").expect("could not save asciidoctor binary"); - reveal_file.write_all(&reveal_bin).expect("could not save asciidoctor binary"); - } - - fn donwload(url: &str) -> Result { - let Ok(response) = reqwest::blocking::get(url) else { - return Err(()); - }; - - let Ok(data) = response.bytes() else { - return Err(()); - }; - - return Ok(data) - } -} - -#[cfg(test)] -mod test { - use std::env; - - - #[test] - fn download() { - println!("{}", env::consts::OS); - assert!(false) - } -} diff --git a/src/app/fs_util/mod.rs b/src/app/fs_util/mod.rs index 50b121c..d44eb2d 100644 --- a/src/app/fs_util/mod.rs +++ b/src/app/fs_util/mod.rs @@ -1,4 +1,4 @@ -use std::fs; +use std::{fs, path::Path, env}; struct RecursivePathFetch { paths: Vec, @@ -58,3 +58,26 @@ pub fn fetch_paths_recursive(path: &str) -> Result, String> { return path_fetch.fetch(); } + +pub fn create_dir_recursive(path: &str) { + let mut validated_path = "".to_string(); + for segment in path.split("/") { + validated_path.push_str(format!("{segment}/").as_str()); + if !directory_exists(&validated_path) { + fs::create_dir(&validated_path).unwrap() + } + } +} + +pub fn directory_exists(path: &String) -> bool { + Path::new(path).is_dir() +} + + +pub fn expand_path(path: String) -> String { + let home_dir = env::var("HOME") + .expect("could not find home dir"); + + return path.replace("~", &home_dir) + +} diff --git a/src/test/fs_util.rs b/src/test/fs_util.rs index 3181e76..6cd4a88 100644 --- a/src/test/fs_util.rs +++ b/src/test/fs_util.rs @@ -1,3 +1,5 @@ +use std::{fs, path::Path}; + use crate::app::fs_util; #[test]