use std::path::{Path, PathBuf};
use crate::component::Component;
use crate::error::Result;
use crate::ssh::CommandOutput;
pub struct RunnerOutput {
pub exit_code: i32,
pub success: bool,
pub stdout: String,
pub stderr: String,
}
use super::ExtensionExecutionContext;
pub struct ExtensionRunner {
execution_context: ExtensionExecutionContext,
settings_overrides: Vec<(String, String)>,
env_vars: Vec<(String, String)>,
script_args: Vec<String>,
path_override: Option<String>,
pre_loaded_component: Option<Component>,
}
impl ExtensionRunner {
pub fn component(mut self, comp: Component) -> Self {
self.pre_loaded_component = Some(comp);
self
}
pub fn for_context(execution_context: ExtensionExecutionContext) -> Self {
Self {
execution_context,
settings_overrides: Vec::new(),
env_vars: Vec::new(),
script_args: Vec::new(),
path_override: None,
pre_loaded_component: None,
}
}
pub fn path_override(mut self, path: Option<String>) -> Self {
self.path_override = path;
self
}
pub fn settings(mut self, overrides: &[(String, String)]) -> Self {
self.settings_overrides.extend(overrides.iter().cloned());
self
}
pub fn env(mut self, key: &str, value: &str) -> Self {
self.env_vars.push((key.to_string(), value.to_string()));
self
}
pub fn env_if(mut self, condition: bool, key: &str, value: &str) -> Self {
if condition {
self.env_vars.push((key.to_string(), value.to_string()));
}
self
}
pub fn env_opt(mut self, key: &str, value: &Option<String>) -> Self {
if let Some(v) = value {
self.env_vars.push((key.to_string(), v.clone()));
}
self
}
pub fn script_args(mut self, args: &[String]) -> Self {
self.script_args.extend(args.iter().cloned());
self
}
pub fn run(&self) -> Result<RunnerOutput> {
let prepared = super::execution::prepare_capability_run(
&self.execution_context,
self.pre_loaded_component.as_ref(),
self.path_override.as_deref(),
&self.settings_overrides,
)?;
let project_path = PathBuf::from(&prepared.execution.component.local_path);
let env_vars = self.prepare_env_vars(
&prepared.execution.extension_path,
&project_path,
&prepared.settings_json,
&prepared.execution.extension_id,
);
let output = self.execute_script(&prepared.execution.extension_path, &env_vars)?;
Ok(RunnerOutput {
exit_code: output.exit_code,
success: output.success,
stdout: output.stdout,
stderr: output.stderr,
})
}
fn prepare_env_vars(
&self,
extension_path: &Path,
project_path: &Path,
settings_json: &str,
extension_name: &str,
) -> Vec<(String, String)> {
super::execution::build_capability_env(
extension_name,
&self.execution_context.component.id,
extension_path,
project_path,
settings_json,
&self.env_vars,
)
}
fn execute_script(
&self,
extension_path: &Path,
env_vars: &[(String, String)],
) -> Result<CommandOutput> {
super::execution::execute_capability_script(
extension_path,
&self.execution_context.script_path,
&self.script_args,
env_vars,
)
}
}