feat: with redone output

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2023-06-17 13:33:10 +02:00
parent 04e8baeefc
commit dc0fa589a5
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
6 changed files with 82 additions and 46 deletions

View File

@ -7,6 +7,8 @@ vars:
registry: kasperhermansen registry: kasperhermansen
scripts: scripts:
install:
type: shell
build_cuddle_image: build_cuddle_image:
type: shell type: shell
args: args:

View File

@ -1,8 +1,6 @@
use std::{ use std::io::{BufRead, BufReader};
env::current_dir, use std::process::Stdio;
path::PathBuf, use std::{env::current_dir, path::PathBuf, process::Command};
process::{Command},
};
use crate::model::CuddleVariable; use crate::model::CuddleVariable;
@ -20,15 +18,7 @@ impl ShellAction {
pub fn execute(self, variables: Vec<CuddleVariable>) -> anyhow::Result<()> { pub fn execute(self, variables: Vec<CuddleVariable>) -> anyhow::Result<()> {
log::debug!("executing shell action: {}", self.path.clone()); log::debug!("executing shell action: {}", self.path.clone());
log::info!( log::info!("Starting running shell action: {}", self.path.clone());
"
===
Starting running shell action: {}
===
",
self.path.clone()
);
let path = PathBuf::from(self.path.clone()); let path = PathBuf::from(self.path.clone());
if !path.exists() { if !path.exists() {
@ -41,6 +31,8 @@ Starting running shell action: {}
let mut process = Command::new(path.clone()) let mut process = Command::new(path.clone())
.current_dir(current_dir) .current_dir(current_dir)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.envs(variables.iter().map(|v| { .envs(variables.iter().map(|v| {
log::trace!("{:?}", v); log::trace!("{:?}", v);
@ -48,6 +40,20 @@ Starting running shell action: {}
})) }))
.spawn()?; .spawn()?;
if let Some(ref mut stdout) = process.stdout {
for line in BufReader::new(stdout).lines() {
let line = line.unwrap();
println!("[{}] {}", self.name, line);
}
}
if let Some(ref mut stderr) = process.stderr {
for line in BufReader::new(stderr).lines() {
let line = line.unwrap();
println!("[{}] {}", self.name, line);
}
}
let status = process.wait()?; let status = process.wait()?;
match status.code() { match status.code() {
@ -55,8 +61,6 @@ Starting running shell action: {}
log::warn!("process exited without code") log::warn!("process exited without code")
} }
Some(n) => { Some(n) => {
log::info!("process exited with code: {}", n);
if n > 0 { if n > 0 {
return Err(anyhow::anyhow!( return Err(anyhow::anyhow!(
"{} exited with: {}", "{} exited with: {}",
@ -67,14 +71,7 @@ Starting running shell action: {}
} }
} }
log::info!( log::info!("Finished running shell action");
"
===
Finished running shell action
===
"
);
Ok(()) Ok(())
} }

View File

@ -21,7 +21,7 @@ use self::subcommands::render_template::RenderTemplateCommand;
pub struct CuddleCli { pub struct CuddleCli {
scripts: Vec<CuddleAction>, scripts: Vec<CuddleAction>,
variables: Vec<CuddleVariable>, variables: Vec<CuddleVariable>,
context: Arc<Mutex<Vec<CuddleContext>>>, context: Option<Arc<Mutex<Vec<CuddleContext>>>>,
command: Option<Command>, command: Option<Command>,
tmp_dir: Option<PathBuf>, tmp_dir: Option<PathBuf>,
config: CuddleConfig, config: CuddleConfig,
@ -29,7 +29,7 @@ pub struct CuddleCli {
impl CuddleCli { impl CuddleCli {
pub fn new( pub fn new(
context: Arc<Mutex<Vec<CuddleContext>>>, context: Option<Arc<Mutex<Vec<CuddleContext>>>>,
config: CuddleConfig, config: CuddleConfig,
) -> anyhow::Result<CuddleCli> { ) -> anyhow::Result<CuddleCli> {
let mut cli = CuddleCli { let mut cli = CuddleCli {
@ -41,17 +41,24 @@ impl CuddleCli {
config, config,
}; };
match context {
Some(_) => {
cli = cli cli = cli
.process_variables() .process_variables()
.process_scripts() .process_scripts()
.process_templates()? .process_templates()?
.build_cli(); .build_cli();
}
None => {
cli = cli.build_bare_cli();
}
}
Ok(cli) Ok(cli)
} }
fn process_variables(mut self) -> Self { fn process_variables(mut self) -> Self {
if let Ok(context_iter) = self.context.clone().lock() { if let Ok(context_iter) = self.context.clone().unwrap().lock() {
for ctx in context_iter.iter() { for ctx in context_iter.iter() {
if let Some(variables) = ctx.plan.vars.clone() { if let Some(variables) = ctx.plan.vars.clone() {
for (name, var) in variables { for (name, var) in variables {
@ -87,7 +94,7 @@ impl CuddleCli {
} }
fn process_scripts(mut self) -> Self { fn process_scripts(mut self) -> Self {
if let Ok(context_iter) = self.context.clone().lock() { if let Ok(context_iter) = self.context.clone().unwrap().lock() {
for ctx in context_iter.iter() { for ctx in context_iter.iter() {
if let Some(scripts) = ctx.plan.scripts.clone() { if let Some(scripts) = ctx.plan.scripts.clone() {
for (name, script) in scripts { for (name, script) in scripts {
@ -124,7 +131,7 @@ impl CuddleCli {
// Handle all templating with variables and such. // Handle all templating with variables and such.
// TODO: use actual templating engine, for new we just copy templates to the final folder // TODO: use actual templating engine, for new we just copy templates to the final folder
if let Ok(context_iter) = self.context.clone().lock() { if let Ok(context_iter) = self.context.clone().unwrap().lock() {
for ctx in context_iter.iter() { for ctx in context_iter.iter() {
let mut template_path = ctx.path.clone(); let mut template_path = ctx.path.clone();
template_path.push("templates"); template_path.push("templates");
@ -166,6 +173,22 @@ impl CuddleCli {
self self
} }
fn build_bare_cli(mut self) -> Self {
let mut root_cmd = Command::new("cuddle")
.version("1.0")
.author("kjuulh <contact@kasperhermansen.com>")
.about("cuddle is your domain specific organization tool. It enabled widespread sharing through repositories, as well as collaborating while maintaining speed and integrity")
.subcommand_required(true)
.arg_required_else_help(true)
.propagate_version(true);
root_cmd = subcommands::init::build_command(root_cmd, self.clone());
self.command = Some(root_cmd);
self
}
pub fn execute(self) -> anyhow::Result<Self> { pub fn execute(self) -> anyhow::Result<Self> {
if let Some(cli) = self.command.clone() { if let Some(cli) = self.command.clone() {
let matches = cli.clone().get_matches(); let matches = cli.clone().get_matches();

View File

@ -1,7 +1,6 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs::{create_dir_all, read, read_dir}; use std::fs::{create_dir_all, read, read_dir};
use std::io::Write; use std::io::Write;
use std::mem::replace;
use std::path::PathBuf; use std::path::PathBuf;
use clap::{ArgMatches, Command}; use clap::{ArgMatches, Command};

View File

@ -25,7 +25,9 @@ pub struct CuddleContext {
pub node_type: CuddleTreeType, pub node_type: CuddleTreeType,
} }
pub fn extract_cuddle(config: CuddleConfig) -> anyhow::Result<Arc<Mutex<Vec<CuddleContext>>>> { pub fn extract_cuddle(
config: CuddleConfig,
) -> anyhow::Result<Option<Arc<Mutex<Vec<CuddleContext>>>>> {
let mut curr_dir = current_dir()?; let mut curr_dir = current_dir()?;
curr_dir.push(".cuddle/"); curr_dir.push(".cuddle/");
let fetch_policy = config.get_fetch_policy()?; let fetch_policy = config.get_fetch_policy()?;
@ -39,6 +41,10 @@ pub fn extract_cuddle(config: CuddleConfig) -> anyhow::Result<Arc<Mutex<Vec<Cudd
// Load main cuddle file. // Load main cuddle file.
let cuddle_yaml = find_root_cuddle()?; let cuddle_yaml = find_root_cuddle()?;
if let None = cuddle_yaml {
return Ok(None);
}
let cuddle_yaml = cuddle_yaml.unwrap();
log::trace!(cuddle_yaml=log::as_debug!(cuddle_yaml); "Find root cuddle"); log::trace!(cuddle_yaml=log::as_debug!(cuddle_yaml); "Find root cuddle");
let cuddle_plan = serde_yaml::from_str::<CuddlePlan>(cuddle_yaml.as_str())?; let cuddle_plan = serde_yaml::from_str::<CuddlePlan>(cuddle_yaml.as_str())?;
@ -74,7 +80,7 @@ pub fn extract_cuddle(config: CuddleConfig) -> anyhow::Result<Arc<Mutex<Vec<Cudd
} }
} }
Ok(context) Ok(Some(context))
} }
fn create_cuddle_local() -> anyhow::Result<PathBuf> { fn create_cuddle_local() -> anyhow::Result<PathBuf> {
@ -131,9 +137,15 @@ fn pull_parent_cuddle_into_local(
Ok(()) Ok(())
} }
fn recurse_parent(path: PathBuf, context: Arc<Mutex<Vec<CuddleContext>>>) -> anyhow::Result<()> { fn recurse_parent(
path: PathBuf,
context: Arc<Mutex<Vec<CuddleContext>>>,
) -> anyhow::Result<Option<()>> {
let cuddle_contents = find_cuddle(path.clone())?; let cuddle_contents = find_cuddle(path.clone())?;
let cuddle_plan = serde_yaml::from_str::<CuddlePlan>(&cuddle_contents)?; if let None = cuddle_contents {
return Ok(None);
}
let cuddle_plan = serde_yaml::from_str::<CuddlePlan>(&cuddle_contents.unwrap())?;
let ctx = context.clone(); let ctx = context.clone();
if let Ok(mut ctxs) = ctx.lock() { if let Ok(mut ctxs) = ctx.lock() {
@ -154,7 +166,7 @@ fn recurse_parent(path: PathBuf, context: Arc<Mutex<Vec<CuddleContext>>>) -> any
} }
CuddleBase::Bool(false) => { CuddleBase::Bool(false) => {
log::debug!("plan is root: finishing up"); log::debug!("plan is root: finishing up");
return Ok(()); return Ok(Some(()));
} }
CuddleBase::String(parent_plan) => { CuddleBase::String(parent_plan) => {
let destination_path = create_cuddle(path.clone())?; let destination_path = create_cuddle(path.clone())?;
@ -169,24 +181,22 @@ fn recurse_parent(path: PathBuf, context: Arc<Mutex<Vec<CuddleContext>>>) -> any
} }
} }
fn find_root_cuddle() -> anyhow::Result<String> { fn find_root_cuddle() -> anyhow::Result<Option<String>> {
// TODO: Make recursive towards root // TODO: Make recursive towards root
let current_dir = env::current_dir()?; let current_dir = env::current_dir()?;
find_cuddle(current_dir) find_cuddle(current_dir)
} }
fn find_cuddle(path: PathBuf) -> anyhow::Result<String> { fn find_cuddle(path: PathBuf) -> anyhow::Result<Option<String>> {
for entry in std::fs::read_dir(path)? { for entry in std::fs::read_dir(path)? {
let entry = entry?; let entry = entry?;
let path = entry.path(); let path = entry.path();
let metadata = std::fs::metadata(&path)?; let metadata = std::fs::metadata(&path)?;
if metadata.is_file() && path.file_name().unwrap() == OsStr::new("cuddle.yaml") { if metadata.is_file() && path.file_name().unwrap() == OsStr::new("cuddle.yaml") {
return Ok(std::fs::read_to_string(path)?); return Ok(Some(std::fs::read_to_string(path)?));
} }
} }
Err(anyhow::anyhow!( Ok(None)
"Could not find 'cuddle.yaml' in the current directory"
))
} }

5
scripts/install.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
cargo install --path cuddle_cli/
cuddle --version