From 571f93ed62306b3dbc6bc3ddd423552a68d9d41c Mon Sep 17 00:00:00 2001 From: quirinecker Date: Mon, 6 Mar 2023 21:21:30 +0100 Subject: [PATCH] added install command for the reveal binary --- Cargo.lock | 10 +++ Cargo.toml | 1 + src/app/commands/mod.rs | 4 +- src/app/commands/reveal.rs | 43 +++++++++++++ src/app/commands/setup.rs | 123 +++++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/app/commands/reveal.rs create mode 100644 src/app/commands/setup.rs diff --git a/Cargo.lock b/Cargo.lock index 33b8306..2c50c96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,6 +139,7 @@ version = "0.2.0" dependencies = [ "bytes", "colored", + "home", "regex", "reqwest", "text_io", @@ -294,6 +295,15 @@ dependencies = [ "libc", ] +[[package]] +name = "home" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" +dependencies = [ + "winapi", +] + [[package]] name = "http" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index 2c277d3..f879ede 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ license-file = "LICENSE.txt" [dependencies] bytes = "1.4.0" colored = "2.0.0" +home = "0.5.4" regex = "1.7.1" reqwest = { version = "0.11.14", features = ["blocking"] } text_io = "0.1.12" diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index fe09cdc..374fb1e 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -2,12 +2,13 @@ use std::collections::HashMap; use traits::Command; -use self::{build::Build, health::Health}; +use self::{build::Build, health::Health, reveal::Reveal}; pub mod traits; pub mod executions; mod build; mod health; +mod reveal; pub struct CommandRegistry { commands: HashMap> @@ -19,6 +20,7 @@ impl CommandRegistry { let registry = self; registry.register("/build".to_string(), Box::new(Build::new()), true); registry.register("/health".to_string(), Box::new(Health::new()), true); + registry.register("/reveal".to_string(), Box::new(Reveal::new()), true); } diff --git a/src/app/commands/reveal.rs b/src/app/commands/reveal.rs new file mode 100644 index 0000000..21ea9d3 --- /dev/null +++ b/src/app/commands/reveal.rs @@ -0,0 +1,43 @@ +use std::{fs::File, io::Write}; + +use crate::app::fs_util; + +use super::traits::Command; + +pub struct Reveal; + +const ASCIIDOC_REVEAL_VERSION: &str= "v4.1.0-rc.5"; + +fn url() -> String { + return format!("https://github.com/asciidoctor/asciidoctor-reveal.js/releases/download/{}/asciidoctor-revealjs-linux", ASCIIDOC_REVEAL_VERSION); +} + +impl Command for Reveal { + fn execute(&self, _args: &std::collections::HashMap) -> Result<(), String> { + Self::install_asciidocto_revealjs(); + return Ok(()) + } + + fn new() -> Self where Self: Sized { + return Self {} + } +} + +impl Reveal { + fn install_asciidocto_revealjs() -> () { + let result = reqwest::blocking::get(url()) + .expect("Could not download reveal. Make sure you are connected to the internet"); + + let binary = result.bytes().expect("could not get binary"); + + let home_path = home::home_dir().expect("could not find home dir"); + let save_path = format!("{}/.docki/asciidoctor-revealjs", home_path.display()); + let save_dir = format!("{}/.docki", home_path.display()); + + fs_util::create_dir_recursive(save_dir.as_str()); + + let mut file = File::create(save_path).expect("could not save binary"); + file.write_all(&binary).expect("could not save binary"); + } + +} diff --git a/src/app/commands/setup.rs b/src/app/commands/setup.rs new file mode 100644 index 0000000..40a7746 --- /dev/null +++ b/src/app/commands/setup.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) + } +}