From 445fb4707aab8d16904f6d0a2d43db134f7cef4f Mon Sep 17 00:00:00 2001 From: Tip ten Brink <75669206+tiptenbrink@users.noreply.github.com> Date: Mon, 29 Apr 2024 23:52:25 +0200 Subject: [PATCH] work on creating public api for commands for tests --- src/next/api.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++ src/next/mod.rs | 4 ++- src/next/run.rs | 6 ++-- src/next/state.rs | 41 ++++++++++++++++++++++ src/state.rs | 14 +++++--- 5 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 src/next/api.rs create mode 100644 src/next/state.rs diff --git a/src/next/api.rs b/src/next/api.rs new file mode 100644 index 0000000..581ad50 --- /dev/null +++ b/src/next/api.rs @@ -0,0 +1,88 @@ +use super::run::{run_command as inner_run_command}; +use crate::state::CliEnvState; +pub use crate::state::StateContext; +use color_eyre::eyre::Report; +use thiserror::Error as ThisError; + +#[non_exhaustive] +pub struct GlobalArguments { + pub context: Option, + pub repo_url: Option, + pub deploy_path: Option, + pub tag: Option, +} + +impl Default for GlobalArguments { + fn default() -> Self { + GlobalArguments { + context: None, + repo_url: None, + deploy_path: None, + tag: None + } + } +} + +impl GlobalArguments { + pub fn cli_env(context: Option, repo_url: Option, deploy_path: Option, tag: Option) -> Self { + GlobalArguments { + context, + repo_url, + deploy_path, + tag + } + } +} + +#[non_exhaustive] +pub struct RunArguments { + pub executable: Option, + pub variables: Vec, + pub archive: Option +} + +impl Default for RunArguments { + fn default() -> Self { + RunArguments { + executable: None, + variables: Vec::new(), + archive: None + } + } +} + +impl RunArguments { + pub fn with(executable: Option, variables: Vec, archive: Option) -> Self { + RunArguments { + executable, + variables, + archive + } + } +} + +impl From for CliEnvState { + fn from(args: GlobalArguments) -> Self { + CliEnvState { + context: args.context, + repo_url: args.repo_url, + deploy_path: args.deploy_path, + tag: args.tag, + } + } +} + +#[derive(ThisError, Debug)] +#[error("{msg} {source}")] +pub struct CommandError { + msg: String, + source: Report +} + +pub fn run_command(global_args: GlobalArguments, args: RunArguments) -> Result<(), CommandError> { + inner_run_command(global_args.into(), args.executable, args.variables, args.archive).map_err(|e| + CommandError { + msg: "An error occurred in the inner application layer.".to_owned(), + source: e + }) +} \ No newline at end of file diff --git a/src/next/mod.rs b/src/next/mod.rs index a52b3e1..ea69495 100644 --- a/src/next/mod.rs +++ b/src/next/mod.rs @@ -1,2 +1,4 @@ pub(crate) mod process; -pub(crate) mod run; \ No newline at end of file +pub(crate) mod run; +pub(crate) mod state; +pub mod api; \ No newline at end of file diff --git a/src/next/run.rs b/src/next/run.rs index f3c6c4c..24183af 100644 --- a/src/next/run.rs +++ b/src/next/run.rs @@ -1,9 +1,11 @@ use color_eyre::eyre::{Context, Report}; use tracing::{debug, instrument}; -use crate::{archives::extract_archive, filesystem::get_dirs, state::{create_state_create, create_state_run, extra_envs, CliEnvState}}; -use super::process::run_entrypoint; + +use crate::{archives::extract_archive, filesystem::get_dirs, state::{create_state_create, extra_envs, CliEnvState}}; + +use super::{process::run_entrypoint, state::create_state_run}; #[instrument(name = "run", level = "debug", skip_all)] pub(crate) fn run_command(cli_state: CliEnvState, executable: Option, variables: Vec, archive: Option) -> Result<(), Report> { diff --git a/src/next/state.rs b/src/next/state.rs new file mode 100644 index 0000000..742a553 --- /dev/null +++ b/src/next/state.rs @@ -0,0 +1,41 @@ +use std::path::Path; + +use color_eyre::eyre::Report; +use relative_path::RelativePath; +use tracing::{debug, span, Level}; + +use crate::{config::ConfigVar, state::{create_state, CliEnvRunState, CliEnvState, State}}; + +/// Parses the list of strings given and interprets them as each pair of two being a secret key and target +/// env name. +fn parse_cli_envs(envs: Vec) -> Vec { + // Our chunk size is 2 so we know first and second exist + // Any final element that does not have something to pair with will be ommitted + envs.chunks_exact(2) + .map(|c| ConfigVar { + key: c.first().unwrap().to_owned(), + env_name: c.get(1).unwrap().to_owned(), + }) + .collect() +} + +/// Creates the state that is used to run the executable. Adds envs provided through CLI to `create_state`. +pub(crate) fn create_state_run( + cli_state: CliEnvState, + exe_name: Option, + envs: Vec, + path: Option<&Path>, + deploy_path: Option<&RelativePath>, + load_tag: bool, +) -> Result { + // Exits when the function returns + let run_state_span = span!(Level::DEBUG, "run_state"); + let _enter = run_state_span.enter(); + + let cli_run_state = CliEnvRunState { + exe_name, + envs: parse_cli_envs(envs), + }; + debug!("Parsed CLI envs as {:?}", cli_run_state); + Ok(create_state(cli_state, Some(cli_run_state), path, deploy_path, load_tag)?) +} \ No newline at end of file diff --git a/src/state.rs b/src/state.rs index e9dc2bf..de745e4 100644 --- a/src/state.rs +++ b/src/state.rs @@ -17,8 +17,12 @@ use thiserror::Error as ThisError; use tracing::{debug, span, Level}; +/// The different contexts that tidploy will use to populate its configuration. 'None' means it will +/// not consider that it is currently in a Git project and will only pick up configuration in its +/// current directory. +#[non_exhaustive] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)] -pub(crate) enum StateContext { +pub enum StateContext { None, GitRemote, GitLocal, @@ -83,9 +87,9 @@ pub(crate) enum LoadError { } #[derive(Clone, Debug)] -struct CliEnvRunState { - envs: Vec, - exe_name: Option, +pub(crate) struct CliEnvRunState { + pub(crate) envs: Vec, + pub(crate) exe_name: Option, } #[derive(Clone, Debug)] @@ -338,7 +342,7 @@ pub(crate) fn create_state_run( /// Create a new state, merging the cli_state, env var state and config state and potentially loading it from the /// context of the supplied path (or current directory if not provided). If cli_run_state is None, no run_state is /// loaded. -fn create_state( +pub(crate) fn create_state( cli_state: CliEnvState, cli_run_state: Option, project_path: Option<&Path>,