feat: scripts can run from plan
This commit is contained in:
parent
2fadde0f8a
commit
b0261de87e
@ -19,6 +19,24 @@ impl Run {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(plan) = &ctx.plan {
|
||||||
|
if let Some(scripts) = &plan.scripts {
|
||||||
|
let existing_cmds = run_cmd
|
||||||
|
.get_subcommands()
|
||||||
|
.map(|s| s.get_name().to_string())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for name in scripts.items.keys() {
|
||||||
|
if existing_cmds.contains(name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd = clap::Command::new(name.to_string());
|
||||||
|
run_cmd = run_cmd.subcommand(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
root.subcommand(run_cmd)
|
root.subcommand(run_cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,14 +49,27 @@ impl Run {
|
|||||||
anyhow::bail!("failed to find a matching run command")
|
anyhow::bail!("failed to find a matching run command")
|
||||||
};
|
};
|
||||||
|
|
||||||
let scripts_ctx = ctx.project.scripts.as_ref().expect("to find scripts");
|
if let Some(scripts_ctx) = &ctx.project.scripts {
|
||||||
let Some(script_ctx) = scripts_ctx.items.get(name) else {
|
if let Some(script_ctx) = scripts_ctx.items.get(name) {
|
||||||
anyhow::bail!("failed to find script: {}", name);
|
ScriptExecutor::new(project_path.into(), ctx.clone())
|
||||||
};
|
.run(script_ctx, name)
|
||||||
|
.await?;
|
||||||
|
|
||||||
ScriptExecutor::new(project_path.into(), ctx.clone())
|
return Ok(());
|
||||||
.run(script_ctx, name)
|
}
|
||||||
.await?;
|
}
|
||||||
|
|
||||||
|
if let Some(plan) = &ctx.plan {
|
||||||
|
if let Some(scripts_ctx) = &plan.scripts {
|
||||||
|
if let Some(script_ctx) = scripts_ctx.items.get(name) {
|
||||||
|
ScriptExecutor::new(project_path.into(), ctx.clone())
|
||||||
|
.run(script_ctx, name)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,44 @@ impl ScriptExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&self, script_ctx: &Script, name: &str) -> anyhow::Result<()> {
|
pub async fn run(&self, script_ctx: &Script, name: &str) -> anyhow::Result<()> {
|
||||||
match script_ctx {
|
if self.run_project(script_ctx, name).await? {
|
||||||
Script::Shell {} => ShellExecutor::from(self).execute(name).await?,
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.run_plan(script_ctx, name).await? {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn run_project(&self, script_ctx: &Script, name: &str) -> anyhow::Result<bool> {
|
||||||
|
match script_ctx {
|
||||||
|
Script::Shell {} => {
|
||||||
|
if matches!(
|
||||||
|
ShellExecutor::from(self).execute(name).await?,
|
||||||
|
shell::ScriptStatus::Found
|
||||||
|
) {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run_plan(&self, script_ctx: &Script, name: &str) -> anyhow::Result<bool> {
|
||||||
|
match script_ctx {
|
||||||
|
Script::Shell {} => {
|
||||||
|
if matches!(
|
||||||
|
ShellExecutor::from_plan(self).execute(name).await?,
|
||||||
|
shell::ScriptStatus::Found
|
||||||
|
) {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::process::Stdio;
|
use std::{path::PathBuf, process::Stdio};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
@ -6,15 +6,26 @@ use super::ScriptExecutor;
|
|||||||
|
|
||||||
pub struct ShellExecutor {
|
pub struct ShellExecutor {
|
||||||
root: ScriptExecutor,
|
root: ScriptExecutor,
|
||||||
|
ty: ShellType,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ScriptStatus {
|
||||||
|
Found,
|
||||||
|
NotFound,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShellType {
|
||||||
|
Plan,
|
||||||
|
Project,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShellExecutor {
|
impl ShellExecutor {
|
||||||
pub async fn execute(&self, name: &str) -> anyhow::Result<()> {
|
pub async fn execute(&self, name: &str) -> anyhow::Result<ScriptStatus> {
|
||||||
let path = &self.root.project_path;
|
let path = &self.get_path();
|
||||||
let script_path = path.join("scripts").join(format!("{name}.sh"));
|
let script_path = path.join("scripts").join(format!("{name}.sh"));
|
||||||
|
|
||||||
if !script_path.exists() {
|
if !script_path.exists() {
|
||||||
anyhow::bail!("script was not found at: {}", script_path.display());
|
return Ok(ScriptStatus::NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = tokio::process::Command::new(&script_path);
|
let mut cmd = tokio::process::Command::new(&script_path);
|
||||||
@ -37,7 +48,21 @@ impl ShellExecutor {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(ScriptStatus::Found)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_path(&self) -> PathBuf {
|
||||||
|
match self.ty {
|
||||||
|
ShellType::Plan => self.root.project_path.join(".forest").join("plan"),
|
||||||
|
ShellType::Project => self.root.project_path.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_plan(value: &ScriptExecutor) -> Self {
|
||||||
|
Self {
|
||||||
|
root: value.clone(),
|
||||||
|
ty: ShellType::Plan,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +70,7 @@ impl From<&ScriptExecutor> for ShellExecutor {
|
|||||||
fn from(value: &ScriptExecutor) -> Self {
|
fn from(value: &ScriptExecutor) -> Self {
|
||||||
Self {
|
Self {
|
||||||
root: value.clone(),
|
root: value.clone(),
|
||||||
|
ty: ShellType::Project,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user