From faf15d13983032b3a374cb3aebabd815c1a2529a Mon Sep 17 00:00:00 2001 From: kjuulh Date: Wed, 10 Aug 2022 16:46:56 +0200 Subject: [PATCH] Added shell action --- Cargo.lock | 21 +++++++++++ cuddle_cli/Cargo.toml | 1 + cuddle_cli/src/actions/mod.rs | 1 + cuddle_cli/src/actions/shell.rs | 54 ++++++++++++++++++++++++++++ cuddle_cli/src/cli.rs | 63 ++++++++++++++++++++++++++++----- cuddle_cli/src/config.rs | 26 ++++++++++++++ cuddle_cli/src/context.rs | 20 +++++++---- cuddle_cli/src/main.rs | 11 +++--- examples/base/scripts/build.sh | 3 ++ 9 files changed, 181 insertions(+), 19 deletions(-) create mode 100644 cuddle_cli/src/actions/mod.rs create mode 100644 cuddle_cli/src/actions/shell.rs create mode 100644 cuddle_cli/src/config.rs create mode 100755 examples/base/scripts/build.sh diff --git a/Cargo.lock b/Cargo.lock index 257f14e..3e96294 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,12 +80,33 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", + "envconfig", "git2", "serde", "serde_yaml", "walkdir", ] +[[package]] +name = "envconfig" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea81cc7e21f55a9d9b1efb6816904978d0bfbe31a50347cb24b2e75564bcac9b" +dependencies = [ + "envconfig_derive", +] + +[[package]] +name = "envconfig_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfca278e5f84b45519acaaff758ebfa01f18e96998bc24b8f1b722dd804b9bf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "form_urlencoded" version = "1.0.1" diff --git a/cuddle_cli/Cargo.toml b/cuddle_cli/Cargo.toml index c2ebe7e..98b1eb8 100644 --- a/cuddle_cli/Cargo.toml +++ b/cuddle_cli/Cargo.toml @@ -12,3 +12,4 @@ serde_yaml = "0.9.4" walkdir = "2.3.2" git2 = { version = "0.15.0", features = ["ssh"] } clap = "3.2.16" +envconfig = "0.10.0" diff --git a/cuddle_cli/src/actions/mod.rs b/cuddle_cli/src/actions/mod.rs new file mode 100644 index 0000000..327cf1b --- /dev/null +++ b/cuddle_cli/src/actions/mod.rs @@ -0,0 +1 @@ +pub mod shell; diff --git a/cuddle_cli/src/actions/shell.rs b/cuddle_cli/src/actions/shell.rs new file mode 100644 index 0000000..a6eb17c --- /dev/null +++ b/cuddle_cli/src/actions/shell.rs @@ -0,0 +1,54 @@ +use std::{ + io::{BufRead, BufReader}, + process::{Command, Stdio}, +}; + +pub struct ShellAction { + path: String, +} + +impl ShellAction { + pub fn new(path: String) -> Self { + Self { path } + } + + pub fn execute(self) -> anyhow::Result<()> { + println!("executing shell action: {}", self.path.clone()); + + println!( + " +=== +Starting running shell action: {} +=== +", + self.path.clone() + ); + + let mut process = Command::new(self.path) + .current_dir(".") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + { + let stdout = process.stdout.as_mut().unwrap(); + let stdout_reader = BufReader::new(stdout); + let mut stdout_lines = stdout_reader.lines(); + while let Some(Ok(line)) = stdout_lines.next() { + println!("{}", line); + } + } + + process.wait()?; + + println!( + " +=== +Finished running shell action +=== +" + ); + + Ok(()) + } +} diff --git a/cuddle_cli/src/cli.rs b/cuddle_cli/src/cli.rs index 7816950..1b829f8 100644 --- a/cuddle_cli/src/cli.rs +++ b/cuddle_cli/src/cli.rs @@ -3,9 +3,10 @@ use std::{ sync::{Arc, Mutex}, }; +use anyhow::anyhow; use clap::Command; -use crate::{context::CuddleContext, model::CuddleScript}; +use crate::{actions, context::CuddleContext, model::CuddleScript}; #[derive(Debug, Clone)] #[allow(dead_code)] @@ -22,8 +23,23 @@ impl CuddleAction { pub fn execute(self) { match self.script { - CuddleScript::Shell(s) => {} - CuddleScript::Dagger(d) => {} + CuddleScript::Shell(_s) => { + match actions::shell::ShellAction::new(format!( + "{}/scripts/{}.sh", + self.path + .to_str() + .expect("action doesn't have a name, this should never happen"), + self.name + )) + .execute() + { + Ok(()) => {} + Err(e) => { + eprintln!("{}", e) + } + } + } + CuddleScript::Dagger(_d) => {} } } } @@ -68,8 +84,7 @@ impl<'a> CuddleCli<'a> { .version("1.0") .author("kjuulh ") .about("cuddle is your domain specific organization tool. It enabled widespread sharing through repositories, as well as collaborating while maintaining speed and integrity") - .propagate_version(true) - .arg_required_else_help(true); + .propagate_version(true); let mut execute_cmd = Command::new("x").about("x is your entry into your domains scripts, scripts inherited from parents will also be present here"); @@ -77,6 +92,7 @@ impl<'a> CuddleCli<'a> { let action_cmd = Command::new(script.name.clone()); // TODO: Some way to add an about for clap, requires conversion from String -> &str + execute_cmd = execute_cmd.subcommand(action_cmd); } @@ -87,11 +103,40 @@ impl<'a> CuddleCli<'a> { self } - pub fn execute(self) -> Self { - if let Some(cli) = self.command.clone() { - let _ = cli.get_matches(); + pub fn execute(self) -> anyhow::Result { + if let Some(mut cli) = self.command.clone() { + let matches = cli.clone().get_matches(); + + let res = match matches.subcommand() { + Some(("x", exe_submatch)) => { + println!("executing: x"); + + match exe_submatch.subcommand() { + Some((name, _action_matches)) => { + println!("running action: {}", name); + match self.scripts.iter().find(|ele| ele.name == name) { + Some(script) => { + script.clone().execute(); + Ok(()) + } + _ => (Err(anyhow!("could not find a match"))), + } + } + _ => (Err(anyhow!("could not find a match"))), + } + } + _ => (Err(anyhow!("could not find a match"))), + }; + + match res { + Ok(()) => {} + Err(e) => { + eprintln!("{}", e); + let _ = cli.print_long_help(); + } + } } - self + Ok(self) } } diff --git a/cuddle_cli/src/config.rs b/cuddle_cli/src/config.rs new file mode 100644 index 0000000..cb88458 --- /dev/null +++ b/cuddle_cli/src/config.rs @@ -0,0 +1,26 @@ +use envconfig::Envconfig; + +pub enum CuddleFetchPolicy { + Always, + Once, +} + +#[derive(Envconfig, Clone)] +pub struct CuddleConfig { + #[envconfig(from = "CUDDLE_FETCH_POLICY", default = "once")] + fetch_policy: String, +} + +impl CuddleConfig { + pub fn from_env() -> anyhow::Result { + CuddleConfig::init_from_env().map_err(|e| anyhow::Error::from(e)) + } + + pub fn get_fetch_policy(&self) -> anyhow::Result { + match self.fetch_policy.clone().to_lowercase().as_str() { + "always" => Ok(CuddleFetchPolicy::Always), + "once" => Ok(CuddleFetchPolicy::Once), + _ => Err(anyhow::anyhow!("could not parse fetch policy")), + } + } +} diff --git a/cuddle_cli/src/context.rs b/cuddle_cli/src/context.rs index dba0e60..44f74a0 100644 --- a/cuddle_cli/src/context.rs +++ b/cuddle_cli/src/context.rs @@ -7,7 +7,10 @@ use std::{ use git2::{build::RepoBuilder, FetchOptions, RemoteCallbacks}; -use crate::model::{CuddleBase, CuddlePlan}; +use crate::{ + config::{CuddleConfig, CuddleFetchPolicy}, + model::{CuddleBase, CuddlePlan}, +}; #[derive(Debug)] pub struct CuddleContext { @@ -15,11 +18,14 @@ pub struct CuddleContext { pub path: PathBuf, } -pub fn extract_cuddle() -> anyhow::Result>>> { +pub fn extract_cuddle(config: CuddleConfig) -> anyhow::Result>>> { let mut curr_dir = current_dir()?; curr_dir.push(".cuddle/"); - if let Err(res) = std::fs::remove_dir_all(curr_dir) { - println!("{}", res); + let fetch_policy = config.get_fetch_policy()?; + if let CuddleFetchPolicy::Always = fetch_policy { + if let Err(res) = std::fs::remove_dir_all(curr_dir) { + println!("{}", res); + } } // Load main cuddle file @@ -52,8 +58,10 @@ pub fn extract_cuddle() -> anyhow::Result>>> { let mut cuddle_dest = destination_path.clone(); cuddle_dest.push("base"); - pull_parent_cuddle_into_local(parent_plan, cuddle_dest.clone())?; - recurse_parent(cuddle_dest, context.clone())?; + if !cuddle_dest.exists() { + pull_parent_cuddle_into_local(parent_plan, cuddle_dest.clone())?; + recurse_parent(cuddle_dest, context.clone())?; + } } } diff --git a/cuddle_cli/src/main.rs b/cuddle_cli/src/main.rs index c01aea3..b12fc75 100644 --- a/cuddle_cli/src/main.rs +++ b/cuddle_cli/src/main.rs @@ -1,13 +1,16 @@ +use config::CuddleConfig; + +mod actions; mod cli; +mod config; mod context; mod model; fn main() -> anyhow::Result<()> { - let context = context::extract_cuddle()?; - let mut cuddle_cli = cli::CuddleCli::new(context.clone())?; - cuddle_cli = cuddle_cli.execute(); + let config = CuddleConfig::from_env()?; - println!("{:?}", cuddle_cli); + let context = context::extract_cuddle(config.clone())?; + _ = cli::CuddleCli::new(context)?.execute()?; Ok(()) } diff --git a/examples/base/scripts/build.sh b/examples/base/scripts/build.sh new file mode 100755 index 0000000..bc00b69 --- /dev/null +++ b/examples/base/scripts/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "Ran build"