@@ -1,6 +1,10 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
future::{self, Future},
|
||||
ops::Deref,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use rust_builder::RustActionsBuilder;
|
||||
@@ -16,6 +20,10 @@ pub mod rust_builder {
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::actions::CuddleActionsSchema;
|
||||
|
||||
use super::ExecutableActions;
|
||||
|
||||
pub struct RustActionsBuilder {
|
||||
@@ -138,7 +146,7 @@ pub mod rust_builder {
|
||||
.output()
|
||||
.await?;
|
||||
|
||||
let actions: ExecutableActions = match serde_json::from_slice(&output.stdout) {
|
||||
let actions: CuddleActionsSchema = match serde_json::from_slice(&output.stdout) {
|
||||
Ok(output) => output,
|
||||
Err(e) => {
|
||||
let schema_output = std::str::from_utf8(&output.stdout)?;
|
||||
@@ -151,7 +159,7 @@ pub mod rust_builder {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(actions)
|
||||
Ok(actions.to_executable(action_path)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,7 +188,7 @@ impl Actions {
|
||||
Ok(Some(Self { variants }))
|
||||
}
|
||||
|
||||
pub async fn build(&mut self) -> anyhow::Result<Vec<ExecutableActions>> {
|
||||
pub async fn build(&mut self) -> anyhow::Result<ExecutableActions> {
|
||||
let mut executable_actions = Vec::default();
|
||||
|
||||
for variant in &mut self.variants {
|
||||
@@ -194,25 +202,49 @@ impl Actions {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(executable_actions)
|
||||
let mut exec_actions = ExecutableActions::default();
|
||||
for mut actions in executable_actions {
|
||||
exec_actions.actions.append(&mut actions.actions);
|
||||
}
|
||||
|
||||
Ok(exec_actions)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CuddleActionsSchema {
|
||||
actions: Vec<CuddleActionSchema>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CuddleActionSchema {
|
||||
name: String,
|
||||
}
|
||||
|
||||
pub enum ActionVariant {
|
||||
Rust { root_path: PathBuf },
|
||||
Docker,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
#[derive(Default)]
|
||||
pub struct ExecutableActions {
|
||||
actions: Vec<ExecutableAction>,
|
||||
pub actions: Vec<ExecutableAction>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ExecutableAction {
|
||||
name: String,
|
||||
description: String,
|
||||
flags: BTreeMap<String, ExecutableActionFlag>,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub flags: BTreeMap<String, ExecutableActionFlag>,
|
||||
call_fn: LazyResolve,
|
||||
}
|
||||
|
||||
impl ExecutableAction {
|
||||
pub async fn call(&self) -> anyhow::Result<()> {
|
||||
// Bad hack until .call becomes stable
|
||||
(self.call_fn.0)().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -220,3 +252,67 @@ pub enum ExecutableActionFlag {
|
||||
String,
|
||||
Bool,
|
||||
}
|
||||
|
||||
impl CuddleActionsSchema {
|
||||
fn to_executable(self, action_path: &Path) -> anyhow::Result<ExecutableActions> {
|
||||
Ok(ExecutableActions {
|
||||
actions: self
|
||||
.actions
|
||||
.into_iter()
|
||||
.map(|a| {
|
||||
let name = a.name.clone();
|
||||
let action_path = action_path.to_string_lossy().to_string();
|
||||
|
||||
ExecutableAction {
|
||||
name: a.name,
|
||||
description: String::new(),
|
||||
flags: BTreeMap::default(),
|
||||
call_fn: LazyResolve::new(Box::new(move || {
|
||||
let name = name.clone();
|
||||
let action_path = action_path.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
tracing::debug!("calling: {}", name);
|
||||
let mut cmd = tokio::process::Command::new(action_path);
|
||||
cmd.args(["do", &name]);
|
||||
|
||||
let output = cmd.output().await?;
|
||||
let stdout = std::str::from_utf8(&output.stdout)?;
|
||||
for line in stdout.lines() {
|
||||
println!("{}: {}", &name, line);
|
||||
}
|
||||
|
||||
tracing::debug!("finished call for output: {}", &name);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct LazyResolve(
|
||||
Arc<dyn Fn() -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync>,
|
||||
);
|
||||
|
||||
impl LazyResolve {
|
||||
pub fn new(
|
||||
func: Box<
|
||||
dyn Fn() -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync,
|
||||
>,
|
||||
) -> Self {
|
||||
Self(Arc::new(func))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for LazyResolve {
|
||||
type Target =
|
||||
Arc<dyn Fn() -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user