diff --git a/.config/nextest.toml b/.config/nextest.toml
new file mode 100644
index 000000000..8912b7747
--- /dev/null
+++ b/.config/nextest.toml
@@ -0,0 +1,2 @@
+[profile.default]
+leak-timeout = "500ms"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b64b756b..329515006 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,11 +2,14 @@
## unreleased
-* Move `Cli*` types to `peace_cli` crate under `cli::output` module. ([#182])
-* Move `OutputFormat` and `OutputFormatParseError` to `peace_cli_model` crate. ([#182])
+* Move `Cli*` types to `peace_cli` crate under `cli::output` module. ([#182], [#189])
+* Move `OutputFormat` and `OutputFormatParseError` to `peace_cli_model` crate. ([#182], [#189])
+* Render progress and outcome diagram using `dot_ix`. ([#182], [#189], [#191])
[#182]: https://github.com/azriel91/peace/issues/182
+[#189]: https://github.com/azriel91/peace/pull/189
+[#191]: https://github.com/azriel91/peace/pull/191
## 0.0.13 (2024-02-03)
diff --git a/Cargo.toml b/Cargo.toml
index f9032c58e..cfbde3e77 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
@@ -151,7 +154,7 @@ console = "0.15.8"
derivative = "2.2.0"
diff-struct = "0.5.3"
downcast-rs = "1.2.0"
-dot_ix = { version = "0.4.1", default-features = false }
+dot_ix = { version = "0.5.0", default-features = false }
dyn-clone = "1.0.17"
enser = "0.1.4"
erased-serde = "0.4.3"
@@ -160,13 +163,14 @@ futures = "0.3.30"
heck = "0.4.1"
indexmap = "2.2.5"
indicatif = "0.17.8"
-interruptible = "0.2.1"
+interruptible = "0.2.2"
leptos = { version = "0.6" }
leptos_axum = "0.6"
leptos_meta = { version = "0.6" }
leptos_router = { version = "0.6" }
libc = "0.2.153"
miette = "7.2.0"
+own = "0.1.0"
pretty_assertions = "1.4.0"
proc-macro2 = "1.0.78"
quote = "1.0.35"
@@ -189,3 +193,6 @@ type_reg = { version = "0.7.0", features = ["debug", "untagged", "ordered"] }
url = "2.5.0"
wasm-bindgen = "0.2.92"
web-sys = "0.3.69"
+
+[workspace.lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
diff --git a/crate/cfg/Cargo.toml b/crate/cfg/Cargo.toml
index 6bb747510..0e70d40e2 100644
--- a/crate/cfg/Cargo.toml
+++ b/crate/cfg/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/cli/Cargo.toml b/crate/cli/Cargo.toml
index afb347083..a51b8ee74 100644
--- a/crate/cli/Cargo.toml
+++ b/crate/cli/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/cli/src/output/cli_output.rs b/crate/cli/src/output/cli_output.rs
index 0f8bdf5e8..c56d7f1ed 100644
--- a/crate/cli/src/output/cli_output.rs
+++ b/crate/cli/src/output/cli_output.rs
@@ -1,4 +1,6 @@
-use std::fmt::{self, Debug};
+#[cfg(unix)]
+use std::fmt;
+use std::fmt::Debug;
use peace_cli_model::OutputFormat;
use peace_fmt::Presentable;
diff --git a/crate/cli_model/Cargo.toml b/crate/cli_model/Cargo.toml
index d8cc06380..7cc635ee4 100644
--- a/crate/cli_model/Cargo.toml
+++ b/crate/cli_model/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/cmd/Cargo.toml b/crate/cmd/Cargo.toml
index 1c1ddc420..fe649eb99 100644
--- a/crate/cmd/Cargo.toml
+++ b/crate/cmd/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
@@ -21,6 +24,7 @@ cfg-if = { workspace = true }
futures = { workspace = true }
indicatif = { workspace = true, optional = true, features = ["tokio"] }
interruptible = { workspace = true, features = ["stream"] }
+own = { workspace = true }
peace_cfg = { workspace = true }
peace_code_gen = { workspace = true }
peace_core = { workspace = true }
diff --git a/crate/cmd/src/ctx/cmd_ctx.rs b/crate/cmd/src/ctx/cmd_ctx.rs
index 7b736003c..7d34a4da0 100644
--- a/crate/cmd/src/ctx/cmd_ctx.rs
+++ b/crate/cmd/src/ctx/cmd_ctx.rs
@@ -2,6 +2,7 @@
use std::ops::{Deref, DerefMut};
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_rt_model::Workspace;
use crate::ctx::{
@@ -38,8 +39,8 @@ impl CmdCtx {
impl CmdCtx<()> {
/// Returns a `CmdCtxBuilder` for a single profile and no flow.
pub fn builder_no_profile_no_flow<'ctx, AppError, Output>(
- output: &'ctx mut Output,
- workspace: &'ctx Workspace,
+ output: OwnedOrMutRef<'ctx, Output>,
+ workspace: OwnedOrRef<'ctx, Workspace>,
) -> CmdCtxBuilder<
'ctx,
CmdCtxTypesCollectorEmpty,
@@ -50,8 +51,8 @@ impl CmdCtx<()> {
/// Returns a `CmdCtxBuilder` for multiple profiles and no flow.
pub fn builder_multi_profile_no_flow<'ctx, AppError, Output>(
- output: &'ctx mut Output,
- workspace: &'ctx Workspace,
+ output: OwnedOrMutRef<'ctx, Output>,
+ workspace: OwnedOrRef<'ctx, Workspace>,
) -> CmdCtxBuilder<
'ctx,
CmdCtxTypesCollectorEmpty,
@@ -62,8 +63,8 @@ impl CmdCtx<()> {
/// Returns a `CmdCtxBuilder` for multiple profiles and one flow.
pub fn builder_multi_profile_single_flow<'ctx, AppError, Output>(
- output: &'ctx mut Output,
- workspace: &'ctx Workspace,
+ output: OwnedOrMutRef<'ctx, Output>,
+ workspace: OwnedOrRef<'ctx, Workspace>,
) -> CmdCtxBuilder<
'ctx,
CmdCtxTypesCollectorEmpty,
@@ -74,8 +75,8 @@ impl CmdCtx<()> {
/// Returns a `CmdCtxBuilder` for a single profile and flow.
pub fn builder_single_profile_no_flow<'ctx, AppError, Output>(
- output: &'ctx mut Output,
- workspace: &'ctx Workspace,
+ output: OwnedOrMutRef<'ctx, Output>,
+ workspace: OwnedOrRef<'ctx, Workspace>,
) -> CmdCtxBuilder<
'ctx,
CmdCtxTypesCollectorEmpty,
@@ -86,8 +87,8 @@ impl CmdCtx<()> {
/// Returns a `CmdCtxBuilder` for a single profile and flow.
pub fn builder_single_profile_single_flow<'ctx, AppError, Output>(
- output: &'ctx mut Output,
- workspace: &'ctx Workspace,
+ output: OwnedOrMutRef<'ctx, Output>,
+ workspace: OwnedOrRef<'ctx, Workspace>,
) -> CmdCtxBuilder<
'ctx,
CmdCtxTypesCollectorEmpty,
diff --git a/crate/cmd/src/ctx/cmd_ctx_builder.rs b/crate/cmd/src/ctx/cmd_ctx_builder.rs
index e2c1c8608..d675efd64 100644
--- a/crate/cmd/src/ctx/cmd_ctx_builder.rs
+++ b/crate/cmd/src/ctx/cmd_ctx_builder.rs
@@ -4,6 +4,7 @@ use std::{fmt::Debug, hash::Hash};
use futures::stream::{StreamExt, TryStreamExt};
use interruptible::Interruptibility;
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_cfg::ItemId;
use peace_params::ParamsSpecs;
use peace_resources::{
@@ -48,11 +49,11 @@ where
/// See [`OutputWrite`].
///
/// [`OutputWrite`]: peace_rt_model_core::OutputWrite
- output: &'ctx mut CmdCtxBuilderTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxBuilderTypesT::Output>,
/// The interrupt channel receiver if this `CmdExecution` is interruptible.
interruptibility: Interruptibility<'static>,
/// Workspace that the `peace` tool runs in.
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
/// Data held while building `CmdCtx`.
scope_builder: ScopeBuilder,
}
diff --git a/crate/cmd/src/scopes/multi_profile_no_flow.rs b/crate/cmd/src/scopes/multi_profile_no_flow.rs
index 692ebff75..64a4e035c 100644
--- a/crate/cmd/src/scopes/multi_profile_no_flow.rs
+++ b/crate/cmd/src/scopes/multi_profile_no_flow.rs
@@ -1,6 +1,7 @@
use std::{collections::BTreeMap, fmt::Debug, hash::Hash};
use interruptible::InterruptibilityState;
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_core::Profile;
use peace_resources::paths::{PeaceAppDir, PeaceDir, ProfileDir, ProfileHistoryDir, WorkspaceDir};
use peace_rt_model::{
@@ -60,13 +61,13 @@ where
/// See [`OutputWrite`].
///
/// [`OutputWrite`]: peace_rt_model_core::OutputWrite
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
/// Whether the `CmdExecution` is interruptible.
///
/// If it is, this holds the interrupt channel receiver.
interruptibility_state: InterruptibilityState<'static, 'static>,
/// Workspace that the `peace` tool runs in.
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
/// The profiles that are accessible by this command.
profiles: Vec,
/// Profile directories that store params and flows.
@@ -179,9 +180,9 @@ where
/// Returns a new `MultiProfileNoFlow` scope.
#[allow(clippy::too_many_arguments)] // Constructed by proc macro
pub(crate) fn new(
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
interruptibility_state: InterruptibilityState<'static, 'static>,
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
profiles: Vec,
profile_dirs: BTreeMap,
profile_history_dirs: BTreeMap,
@@ -240,12 +241,12 @@ where
/// Returns a reference to the output.
pub fn output(&self) -> &CmdCtxTypesT::Output {
- self.output
+ &self.output
}
/// Returns a mutable reference to the output.
pub fn output_mut(&mut self) -> &mut CmdCtxTypesT::Output {
- self.output
+ &mut self.output
}
/// Returns the interruptibility capability.
@@ -255,7 +256,7 @@ where
/// Returns the workspace that the `peace` tool runs in.
pub fn workspace(&self) -> &Workspace {
- self.workspace
+ &self.workspace
}
/// Returns a reference to the workspace directory.
diff --git a/crate/cmd/src/scopes/multi_profile_single_flow.rs b/crate/cmd/src/scopes/multi_profile_single_flow.rs
index 764966d0c..cba3d7416 100644
--- a/crate/cmd/src/scopes/multi_profile_single_flow.rs
+++ b/crate/cmd/src/scopes/multi_profile_single_flow.rs
@@ -1,6 +1,7 @@
use std::{collections::BTreeMap, fmt::Debug, hash::Hash};
use interruptible::InterruptibilityState;
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_core::Profile;
use peace_params::ParamsSpecs;
use peace_resources::{
@@ -83,13 +84,13 @@ where
/// See [`OutputWrite`].
///
/// [`OutputWrite`]: peace_rt_model_core::OutputWrite
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
/// Whether the `CmdExecution` is interruptible.
///
/// If it is, this holds the interrupt channel receiver.
interruptibility_state: InterruptibilityState<'static, 'static>,
/// Workspace that the `peace` tool runs in.
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
/// The profiles that are accessible by this command.
profiles: Vec,
/// Profile directories that store params and flows.
@@ -229,9 +230,9 @@ where
/// Returns a new `MultiProfileSingleFlow` scope.
#[allow(clippy::too_many_arguments)] // Constructed by proc macro
pub(crate) fn new(
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
interruptibility_state: InterruptibilityState<'static, 'static>,
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
profiles: Vec,
profile_dirs: BTreeMap,
profile_history_dirs: BTreeMap,
@@ -337,12 +338,12 @@ where
/// Returns a reference to the output.
pub fn output(&self) -> &CmdCtxTypesT::Output {
- self.output
+ &self.output
}
/// Returns a mutable reference to the output.
pub fn output_mut(&mut self) -> &mut CmdCtxTypesT::Output {
- self.output
+ &mut self.output
}
/// Returns the interruptibility capability.
@@ -352,7 +353,7 @@ where
/// Returns the workspace that the `peace` tool runs in.
pub fn workspace(&self) -> &Workspace {
- self.workspace
+ &self.workspace
}
/// Returns a reference to the workspace directory.
diff --git a/crate/cmd/src/scopes/no_profile_no_flow.rs b/crate/cmd/src/scopes/no_profile_no_flow.rs
index 7eab6c904..72ea3d3ac 100644
--- a/crate/cmd/src/scopes/no_profile_no_flow.rs
+++ b/crate/cmd/src/scopes/no_profile_no_flow.rs
@@ -1,6 +1,7 @@
use std::{fmt::Debug, hash::Hash};
use interruptible::InterruptibilityState;
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_resources::paths::{PeaceAppDir, PeaceDir, WorkspaceDir};
use peace_rt_model::{
params::{KeyKnown, KeyMaybe, ParamsKeys, ParamsKeysImpl, ParamsTypeRegs, WorkspaceParams},
@@ -43,13 +44,13 @@ where
/// See [`OutputWrite`].
///
/// [`OutputWrite`]: peace_rt_model_core::OutputWrite
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
/// Whether the `CmdExecution` is interruptible.
///
/// If it is, this holds the interrupt channel receiver.
interruptibility_state: InterruptibilityState<'static, 'static>,
/// Workspace that the `peace` tool runs in.
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
/// Type registries for [`WorkspaceParams`], [`ProfileParams`], and
/// [`FlowParams`] deserialization.
///
@@ -68,9 +69,9 @@ where
CmdCtxTypesT: CmdCtxTypes,
{
pub(crate) fn new(
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
interruptibility_state: InterruptibilityState<'static, 'static>,
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
params_type_regs: ParamsTypeRegs,
workspace_params: WorkspaceParams<
<::WorkspaceParamsKMaybe as KeyMaybe>::Key,
@@ -87,12 +88,12 @@ where
/// Returns a reference to the output.
pub fn output(&self) -> &CmdCtxTypesT::Output {
- self.output
+ &self.output
}
/// Returns a mutable reference to the output.
pub fn output_mut(&mut self) -> &mut CmdCtxTypesT::Output {
- self.output
+ &mut self.output
}
//// Returns the interruptibility capability.
@@ -102,7 +103,7 @@ where
/// Returns the workspace that the `peace` tool runs in.
pub fn workspace(&self) -> &Workspace {
- self.workspace
+ &self.workspace
}
/// Returns a reference to the workspace directory.
diff --git a/crate/cmd/src/scopes/single_profile_no_flow.rs b/crate/cmd/src/scopes/single_profile_no_flow.rs
index d10c23f24..7ad07a042 100644
--- a/crate/cmd/src/scopes/single_profile_no_flow.rs
+++ b/crate/cmd/src/scopes/single_profile_no_flow.rs
@@ -1,6 +1,7 @@
use std::{fmt::Debug, hash::Hash};
use interruptible::InterruptibilityState;
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_core::Profile;
use peace_resources::paths::{PeaceAppDir, PeaceDir, ProfileDir, ProfileHistoryDir, WorkspaceDir};
use peace_rt_model::{
@@ -53,13 +54,13 @@ where
/// See [`OutputWrite`].
///
/// [`OutputWrite`]: peace_rt_model_core::OutputWrite
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
/// Whether the `CmdExecution` is interruptible.
///
/// If it is, this holds the interrupt channel receiver.
interruptibility_state: InterruptibilityState<'static, 'static>,
/// Workspace that the `peace` tool runs in.
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
/// The profile this command operates on.
profile: Profile,
/// Profile directory that stores params and flows.
@@ -159,9 +160,9 @@ where
/// Returns a new `SingleProfileNoFlow` scope.
#[allow(clippy::too_many_arguments)] // Constructed by proc macro
pub(crate) fn new(
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
interruptibility_state: InterruptibilityState<'static, 'static>,
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
profile: Profile,
profile_dir: ProfileDir,
profile_history_dir: ProfileHistoryDir,
@@ -217,12 +218,12 @@ where
/// Returns a reference to the output.
pub fn output(&self) -> &CmdCtxTypesT::Output {
- self.output
+ &self.output
}
/// Returns a mutable reference to the output.
pub fn output_mut(&mut self) -> &mut CmdCtxTypesT::Output {
- self.output
+ &mut self.output
}
/// Returns the interruptibility capability.
@@ -232,7 +233,7 @@ where
/// Returns the workspace that the `peace` tool runs in.
pub fn workspace(&self) -> &Workspace {
- self.workspace
+ &self.workspace
}
/// Returns a reference to the workspace directory.
diff --git a/crate/cmd/src/scopes/single_profile_single_flow.rs b/crate/cmd/src/scopes/single_profile_single_flow.rs
index ea14e9979..c33a6a0c0 100644
--- a/crate/cmd/src/scopes/single_profile_single_flow.rs
+++ b/crate/cmd/src/scopes/single_profile_single_flow.rs
@@ -1,6 +1,7 @@
use std::{fmt::Debug, hash::Hash};
use interruptible::InterruptibilityState;
+use own::{OwnedOrMutRef, OwnedOrRef};
use peace_core::Profile;
use peace_params::ParamsSpecs;
use peace_resources::{
@@ -62,13 +63,13 @@ where
/// See [`OutputWrite`].
///
/// [`OutputWrite`]: peace_rt_model_core::OutputWrite
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
/// Whether the `CmdExecution` is interruptible.
///
/// If it is, this holds the interrupt channel receiver.
interruptibility_state: InterruptibilityState<'static, 'static>,
/// Workspace that the `peace` tool runs in.
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
/// Tracks progress of each function execution.
#[cfg(feature = "output_progress")]
cmd_progress_tracker: peace_rt_model::CmdProgressTracker,
@@ -246,9 +247,9 @@ where
/// Returns a new `SingleProfileSingleFlow` scope.
#[allow(clippy::too_many_arguments)] // Constructed by proc macro
pub(crate) fn new(
- output: &'ctx mut CmdCtxTypesT::Output,
+ output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
interruptibility_state: InterruptibilityState<'static, 'static>,
- workspace: &'ctx Workspace,
+ workspace: OwnedOrRef<'ctx, Workspace>,
#[cfg(feature = "output_progress")]
cmd_progress_tracker: peace_rt_model::CmdProgressTracker,
profile: Profile,
@@ -397,12 +398,12 @@ where
/// Returns a reference to the output.
pub fn output(&self) -> &CmdCtxTypesT::Output {
- self.output
+ &self.output
}
/// Returns a mutable reference to the output.
pub fn output_mut(&mut self) -> &mut CmdCtxTypesT::Output {
- self.output
+ &mut self.output
}
/// Returns the interruptibility capability.
@@ -412,7 +413,7 @@ where
/// Returns the workspace that the `peace` tool runs in.
pub fn workspace(&self) -> &Workspace {
- self.workspace
+ &self.workspace
}
/// Returns a reference to the workspace directory.
diff --git a/crate/cmd_model/Cargo.toml b/crate/cmd_model/Cargo.toml
index 08436dfef..654d285f8 100644
--- a/crate/cmd_model/Cargo.toml
+++ b/crate/cmd_model/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/cmd_model/src/cmd_execution_id.rs b/crate/cmd_model/src/cmd_execution_id.rs
new file mode 100644
index 000000000..ba80de775
--- /dev/null
+++ b/crate/cmd_model/src/cmd_execution_id.rs
@@ -0,0 +1,28 @@
+use std::ops::Deref;
+
+/// ID of a command execution.
+///
+/// Uniqueness is not yet defined -- these may overlap with IDs from different
+/// machines.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct CmdExecutionId(u64);
+
+impl CmdExecutionId {
+ /// Returns a new `CmdExecutionId`.
+ pub fn new(id: u64) -> Self {
+ Self(id)
+ }
+
+ /// Returns the underlying ID.
+ pub fn into_inner(self) -> u64 {
+ self.0
+ }
+}
+
+impl Deref for CmdExecutionId {
+ type Target = u64;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
diff --git a/crate/cmd_model/src/lib.rs b/crate/cmd_model/src/lib.rs
index 699320767..b562e647c 100644
--- a/crate/cmd_model/src/lib.rs
+++ b/crate/cmd_model/src/lib.rs
@@ -8,14 +8,16 @@ pub use indexmap;
pub use crate::{
cmd_block_desc::CmdBlockDesc, cmd_block_outcome::CmdBlockOutcome,
- cmd_execution_error::CmdExecutionError, cmd_outcome::CmdOutcome,
- item_stream_outcome::ItemStreamOutcome, stream_outcome_and_errors::StreamOutcomeAndErrors,
+ cmd_execution_error::CmdExecutionError, cmd_execution_id::CmdExecutionId,
+ cmd_outcome::CmdOutcome, item_stream_outcome::ItemStreamOutcome,
+ stream_outcome_and_errors::StreamOutcomeAndErrors,
value_and_stream_outcome::ValueAndStreamOutcome,
};
mod cmd_block_desc;
mod cmd_block_outcome;
mod cmd_execution_error;
+mod cmd_execution_id;
mod cmd_outcome;
mod item_stream_outcome;
mod stream_outcome_and_errors;
diff --git a/crate/cmd_rt/Cargo.toml b/crate/cmd_rt/Cargo.toml
index 4c914911c..b51062f27 100644
--- a/crate/cmd_rt/Cargo.toml
+++ b/crate/cmd_rt/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/code_gen/Cargo.toml b/crate/code_gen/Cargo.toml
index 40a766963..4d3861b35 100644
--- a/crate/code_gen/Cargo.toml
+++ b/crate/code_gen/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
proc-macro = true
doctest = true
diff --git a/crate/code_gen/src/cmd/impl_build.rs b/crate/code_gen/src/cmd/impl_build.rs
index d09d015ec..239ef320b 100644
--- a/crate/code_gen/src/cmd/impl_build.rs
+++ b/crate/code_gen/src/cmd/impl_build.rs
@@ -150,10 +150,6 @@ fn impl_build_for(
let scope_builder_name = &scope_struct.item_struct().ident;
let scope_type_path = scope.type_path();
- let workspace_dirs_and_storage_borrow = quote! {
- let workspace_dirs = self.workspace.dirs();
- let storage = self.workspace.storage();
- };
let (workspace_params_deserialize, workspace_params_serialize, workspace_params_insert) =
workspace_params_load_save(workspace_params_selection);
@@ -308,13 +304,20 @@ fn impl_build_for(
{
use futures::stream::TryStreamExt;
- // Values shared by subsequent function calls.
- // let workspace_dirs = self.workspace.dirs();
- // let storage = self.workspace.storage();
- #workspace_dirs_and_storage_borrow
-
+ // let workspace = &self.workspace;
+ // let workspace_dirs = workspace.dirs();
+ // let storage = workspace.storage();
+ // let params_type_regs_builder = &self.scope_builder.params_type_regs_builder;
+ // let workspace_params = &mut self.scope_builder.workspace_params_selection.0;
+ //
// let workspace_params_file = WorkspaceParamsFile::from(workspace_dirs.peace_app_dir());
- // self.workspace_params_merge(&workspace_params_file).await?;
+ // self.workspace_params_merge(
+ // storage,
+ // params_type_regs_builder,
+ // workspace_params,
+ // &workspace_params_file,
+ // )
+ //.await?;
#workspace_params_deserialize
// let profile = self
@@ -340,6 +343,7 @@ fn impl_build_for(
#profile_s_ref
// === Cmd dirs === //
+ // let workspace_dirs = self.workspace.dirs();
// --- Single Profile --- //
// let profile_dir = ProfileDir::from((workspace_dirs.peace_app_dir(), profile_s_ref));
// let profile_history_dir = ProfileHistoryDir::from(&profile_dir);
@@ -407,6 +411,12 @@ fn impl_build_for(
// === Profile Params === //
// --- Single --- //
+ // let workspace = &self.workspace;
+ // let workspace_dirs = workspace.dirs();
+ // let storage = workspace.storage();
+ // let params_type_regs_builder = &self.scope_builder.params_type_regs_builder;
+ // let profile_params = &mut self.scope_builder.profile_params_selection.0;
+ //
// let profile_params_file = ProfileParamsFile::from(&profile_dir);
// self.profile_params_merge(&profile_params_file).await?;
// --- Multi --- //
@@ -436,6 +446,12 @@ fn impl_build_for(
// === Flow Params === //
// --- Single --- //
+ // let workspace = &self.workspace;
+ // let workspace_dirs = workspace.dirs();
+ // let storage = workspace.storage();
+ // let params_type_regs_builder = &self.scope_builder.params_type_regs_builder;
+ // let flow_params = &mut self.scope_builder.flow_params_selection.0;
+ //
// let flow_params_file = ProfileParamsFile::from(&flow_dir);
// self.flow_params_merge(&flow_params_file).await?;
// --- Multi --- //
@@ -465,7 +481,10 @@ fn impl_build_for(
// Create directories and write init parameters to storage.
#[cfg(target_arch = "wasm32")]
- peace_rt_model::WorkspaceInitializer::dirs_create(storage, dirs_to_create).await?;
+ {
+ let storage = self.workspace.storage();
+ peace_rt_model::WorkspaceInitializer::dirs_create(storage, dirs_to_create).await?;
+ }
#[cfg(not(target_arch = "wasm32"))]
{
peace_rt_model::WorkspaceInitializer::dirs_create(dirs_to_create).await?;
@@ -504,6 +523,8 @@ fn impl_build_for(
// Serialize params to `PeaceAppDir`.
+ let storage = workspace.storage();
+
// crate::ctx::cmd_ctx_builder::workspace_params_serialize(
// &workspace_params,
// storage,
@@ -950,11 +971,23 @@ fn workspace_params_load_save(
}
WorkspaceParamsSelection::Some => {
let workspace_params_deserialize = quote! {
+ let workspace = &self.workspace;
+ let workspace_dirs = workspace.dirs();
+ let storage = workspace.storage();
+ let params_type_regs_builder = &self.scope_builder.params_type_regs_builder;
+ let workspace_params = &mut self.scope_builder.workspace_params_selection.0;
+
let workspace_params_file = peace_resources::internal::WorkspaceParamsFile::from(
workspace_dirs.peace_app_dir()
);
- self.workspace_params_merge(&workspace_params_file).await?;
+ Self::workspace_params_merge(
+ storage,
+ params_type_regs_builder,
+ workspace_params,
+ &workspace_params_file,
+ )
+ .await?;
};
let workspace_params_serialize = quote! {
crate::ctx::cmd_ctx_builder::workspace_params_serialize(
@@ -1014,11 +1047,22 @@ fn profile_params_load_save(
}
ProfileParamsSelection::Some => {
let profile_params_deserialize = quote! {
+ let workspace = &self.workspace;
+ let workspace_dirs = workspace.dirs();
+ let storage = workspace.storage();
+ let params_type_regs_builder = &self.scope_builder.params_type_regs_builder;
+ let profile_params = &mut self.scope_builder.profile_params_selection.0;
+
let profile_params_file = peace_resources::internal::ProfileParamsFile::from(
&profile_dir
);
- self.profile_params_merge(&profile_params_file).await?;
+ Self::profile_params_merge(
+ storage,
+ params_type_regs_builder,
+ profile_params,
+ &profile_params_file,
+ ).await?;
};
let profile_params_serialize = quote! {
crate::ctx::cmd_ctx_builder::profile_params_serialize(
@@ -1147,11 +1191,22 @@ fn flow_params_load_save(
}
FlowParamsSelection::Some => {
let flow_params_deserialize = quote! {
+ let workspace = &self.workspace;
+ let workspace_dirs = workspace.dirs();
+ let storage = workspace.storage();
+ let params_type_regs_builder = &self.scope_builder.params_type_regs_builder;
+ let flow_params = &mut self.scope_builder.flow_params_selection.0;
+
let flow_params_file = peace_resources::internal::FlowParamsFile::from(
&flow_dir
);
- self.flow_params_merge(&flow_params_file).await?;
+ Self::flow_params_merge(
+ storage,
+ params_type_regs_builder,
+ flow_params,
+ &flow_params_file,
+ ).await?;
};
let flow_params_serialize = quote! {
crate::ctx::cmd_ctx_builder::flow_params_serialize(
@@ -1267,6 +1322,7 @@ fn profiles_from_peace_app_dir(
ProfileCount::None | ProfileCount::One => proc_macro2::TokenStream::new(),
ProfileCount::Multiple => match profile_selection {
ProfileSelection::NotSelected => quote! {
+ let workspace_dirs = self.workspace.dirs();
let profiles = crate::ctx::cmd_ctx_builder::profiles_from_peace_app_dir(
workspace_dirs.peace_app_dir(),
None,
@@ -1277,6 +1333,7 @@ fn profiles_from_peace_app_dir(
`ProfileSelection::FromWorkspaceParam`."
),
ProfileSelection::FilterFunction => quote! {
+ let workspace_dirs = self.workspace.dirs();
let profiles_filter_fn = self.scope_builder.profile_selection.0.as_ref();
let profiles = crate::ctx::cmd_ctx_builder::profiles_from_peace_app_dir(
workspace_dirs.peace_app_dir(),
@@ -1326,6 +1383,9 @@ fn profile_s_ref(scope: Scope, profile_selection: ProfileSelection) -> proc_macr
/// ```
fn cmd_dirs(scope: Scope) -> proc_macro2::TokenStream {
let mut dirs_tokens = proc_macro2::TokenStream::new();
+ dirs_tokens.extend(quote! {
+ let workspace_dirs = self.workspace.dirs();
+ });
match scope.profile_count() {
ProfileCount::None => {}
diff --git a/crate/code_gen/src/cmd/impl_constructor.rs b/crate/code_gen/src/cmd/impl_constructor.rs
index 44f3b0012..cba9a788c 100644
--- a/crate/code_gen/src/cmd/impl_constructor.rs
+++ b/crate/code_gen/src/cmd/impl_constructor.rs
@@ -73,8 +73,8 @@ pub fn impl_constructor(scope_struct: &ScopeStruct) -> proc_macro2::TokenStream
{
/// Returns a `CmdCtxBuilder` for a single profile and flow.
pub fn #constructor_method_name(
- output: &'ctx mut Output,
- workspace: &'ctx peace_rt_model::Workspace,
+ output: own::OwnedOrMutRef<'ctx, Output>,
+ workspace: own::OwnedOrRef<'ctx, peace_rt_model::Workspace>,
) -> Self
{
let scope_builder = #scope_builder_name {
diff --git a/crate/code_gen/src/cmd/impl_params_merge.rs b/crate/code_gen/src/cmd/impl_params_merge.rs
index 3cbbc22d2..d1743bbfd 100644
--- a/crate/code_gen/src/cmd/impl_params_merge.rs
+++ b/crate/code_gen/src/cmd/impl_params_merge.rs
@@ -44,7 +44,8 @@ fn impl_params_merge_for(
let params_type_reg_method_name = params_scope.params_type_reg_method_name();
let params_file_name = params_scope.params_file_name();
let params_file_type = params_scope.params_file_type();
- let params_selection_name = params_scope.params_selection_name();
+ let params_map_type = params_scope.params_map_type();
+ let params_k_type_param = params_scope.params_k_type_param();
let doc_summary = {
let params_scope_str = params_scope.to_str();
@@ -74,24 +75,59 @@ fn impl_params_merge_for(
.build()
};
+ let params_keys_type = match params_scope {
+ ParamsScope::Workspace => quote! {
+ peace_rt_model::params::ParamsKeysImpl<
+ peace_rt_model::params::KeyKnown,
+ ProfileParamsKMaybe,
+ FlowParamsKMaybe,
+ >,
+ },
+ ParamsScope::Profile => quote! {
+ peace_rt_model::params::ParamsKeysImpl<
+ WorkspaceParamsKMaybe,
+ peace_rt_model::params::KeyKnown,
+ FlowParamsKMaybe,
+ >,
+ },
+ ParamsScope::Flow => quote! {
+ peace_rt_model::params::ParamsKeysImpl<
+ WorkspaceParamsKMaybe,
+ ProfileParamsKMaybe,
+ peace_rt_model::params::KeyKnown,
+ >,
+ },
+ };
+
quote! {
#impl_header
{
#[doc = #doc_summary]
// async fn workspace_params_merge
async fn #params_merge_method_name(
- &mut self,
+ storage: &peace_rt_model::Storage,
+ // params_type_regs_builder:
+ // &peace_rt_model::params::ParamsTypeRegsBuilder<
+ // peace_rt_model::params::ParamsKeysImpl<
+ // peace_rt_model::params::KeyKnown,
+ // ProfileParamsKMaybe,
+ // FlowParamsKMaybe,
+ // >,
+ // >,
+ params_type_regs_builder:
+ &peace_rt_model::params::ParamsTypeRegsBuilder<#params_keys_type>,
+ // params: &mut peace_rt_model::params::WorkspaceParams,
+ params: &mut peace_rt_model::params::#params_map_type<#params_k_type_param>,
// workspace_params_file: &peace_resources::internal::WorkspaceParamsFile,
#params_file_name: &peace_resources::internal::#params_file_type,
) -> Result<(), peace_rt_model::Error> {
- let storage = self.workspace.storage();
let params_deserialized = peace_rt_model::WorkspaceInitializer::#params_deserialize_method_name::<
// WorkspaceParamsK,
#p_keys_key_maybe_key
>(
storage,
- // self.scope_builder.params_type_regs_builder.workspace_params_type_reg(),
- self.scope_builder.params_type_regs_builder.#params_type_reg_method_name(),
+ // params_type_regs_builder.workspace_params_type_reg(),
+ params_type_regs_builder.#params_type_reg_method_name(),
#params_file_name,
)
.await?;
@@ -101,7 +137,6 @@ fn impl_params_merge_for(
// or, copy `params_deserialized` to `params` where
// there isn't a value.
- let params = &mut self.scope_builder.#params_selection_name.0;
if params.is_empty() {
*params = params_deserialized;
} else {
diff --git a/crate/core/Cargo.toml b/crate/core/Cargo.toml
index 18204130d..09fa92c1b 100644
--- a/crate/core/Cargo.toml
+++ b/crate/core/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/data/Cargo.toml b/crate/data/Cargo.toml
index dceee9b56..1bdf99108 100644
--- a/crate/data/Cargo.toml
+++ b/crate/data/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/data_derive/Cargo.toml b/crate/data_derive/Cargo.toml
index f92b53412..6b54548df 100644
--- a/crate/data_derive/Cargo.toml
+++ b/crate/data_derive/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
proc-macro = true
doctest = false
diff --git a/crate/diff/Cargo.toml b/crate/diff/Cargo.toml
index cf4f02db9..2f8d3c3ac 100644
--- a/crate/diff/Cargo.toml
+++ b/crate/diff/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/flow_model/Cargo.toml b/crate/flow_model/Cargo.toml
index 4fff594b5..966ae52c9 100644
--- a/crate/flow_model/Cargo.toml
+++ b/crate/flow_model/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[dependencies]
dot_ix = { workspace = true, default-features = false }
fn_graph = { workspace = true, features = ["graph_info"] }
diff --git a/crate/flow_model/src/flow_spec_info.rs b/crate/flow_model/src/flow_spec_info.rs
index f05496c65..f630b52d2 100644
--- a/crate/flow_model/src/flow_spec_info.rs
+++ b/crate/flow_model/src/flow_spec_info.rs
@@ -1,8 +1,8 @@
use std::collections::HashSet;
use dot_ix::model::{
- common::{EdgeId, NodeHierarchy, NodeId},
- info_graph::{GraphDir, IndexMap, InfoGraph, NodeInfo},
+ common::{EdgeId, Edges, NodeHierarchy, NodeId, NodeNames},
+ info_graph::{GraphDir, InfoGraph},
};
use fn_graph::{daggy::Walker, Edge, FnId, GraphInfo};
use peace_core::FlowId;
@@ -48,13 +48,13 @@ impl FlowSpecInfo {
);
let edges = progress_node_edges(graph_info);
- let node_infos = node_infos(graph_info);
+ let node_names = node_names(graph_info);
InfoGraph::builder()
.with_direction(GraphDir::Vertical)
.with_hierarchy(hierarchy)
.with_edges(edges)
- .with_node_infos(node_infos)
+ .with_node_names(node_names)
.build()
}
@@ -82,13 +82,13 @@ impl FlowSpecInfo {
);
let edges = outcome_node_edges(graph_info);
- let node_infos = node_infos(graph_info);
+ let node_names = node_names(graph_info);
InfoGraph::builder()
.with_direction(GraphDir::Vertical)
.with_hierarchy(hierarchy)
.with_edges(edges)
- .with_node_infos(node_infos)
+ .with_node_names(node_names)
.build()
}
}
@@ -113,7 +113,26 @@ fn outcome_node_hierarchy(
// For outcome graphs, child nodes that:
//
// * are contained by parents nodes are represented as a nested node.
- // * reference data from parent nodes are represented by forward edges
+ // * reference data from parent nodes are represented by forward edges.
+ //
+ // We actually want to determine nesting from the following information:
+ //
+ // * Host machines:
+ //
+ // A file transfer would have a source host, source path, dest host, dest
+ // path, and these exist in the same Item's parameters.
+ //
+ // * Physical nesting:
+ //
+ // - Configuration that lives inside a server.
+ // - Cloud resource that lives inside a subnet.
+ //
+ // Should this be provided by the item or tool developer?
+ //
+ // Probably the item. The item knows its parameters (which may be mapped
+ // from other items' state), so the containment is returned based on the
+ // item knowing its parent container is from a source / destination
+ // parameter.
if matches!(
graph_info.edge_weight(edge_index).copied(),
Some(Edge::Contains)
@@ -139,9 +158,9 @@ fn outcome_node_hierarchy(
}
/// Returns the list of edges between items in the graph.
-fn outcome_node_edges(graph_info: &GraphInfo) -> IndexMap {
+fn outcome_node_edges(graph_info: &GraphInfo) -> Edges {
graph_info.iter_insertion_with_indices().fold(
- IndexMap::with_capacity(graph_info.node_count()),
+ Edges::with_capacity(graph_info.node_count()),
|mut edges, (node_index, item_spec_info)| {
//
let children = graph_info.children(node_index);
@@ -183,18 +202,22 @@ fn outcome_node_edges(graph_info: &GraphInfo) -> IndexMap) -> IndexMap {
+fn progress_node_edges(graph_info: &GraphInfo) -> Edges {
graph_info.iter_insertion_with_indices().fold(
- IndexMap::with_capacity(graph_info.node_count()),
+ Edges::with_capacity(graph_info.node_count()),
|mut edges, (node_index, item_spec_info)| {
//
let children = graph_info.children(node_index);
children
.iter(graph_info)
.filter_map(|(edge_index, child_node_index)| {
+ // For progress graphs, child nodes that:
//
- // * are contained by parents nodes are represented as a nested node.
- // * reference data from parent nodes are represented by forward edges
+ // * are contained by parents nodes
+ // * reference data from parent nodes
+ //
+ // are both represented by forward edges, since this is their sequential
+ // ordering.
if matches!(
graph_info.edge_weight(edge_index).copied(),
Some(Edge::Logic | Edge::Contains)
@@ -222,18 +245,18 @@ fn progress_node_edges(graph_info: &GraphInfo) -> IndexMap) -> IndexMap {
+fn node_names(graph_info: &GraphInfo) -> NodeNames {
graph_info.iter_insertion_with_indices().fold(
- IndexMap::with_capacity(graph_info.node_count()),
- |mut node_infos, (_node_index, item_spec_info)| {
+ NodeNames::with_capacity(graph_info.node_count()),
+ |mut node_names, (_node_index, item_spec_info)| {
let item_id = item_spec_info_to_node_id(item_spec_info);
// Note: This does not have to be the ID, it can be a human readable name.
- let node_info = NodeInfo::new(item_id.to_string());
+ let node_name = item_id.to_string();
- node_infos.insert(item_id, node_info);
+ node_names.insert(item_id, node_name);
- node_infos
+ node_names
},
)
}
diff --git a/crate/fmt/Cargo.toml b/crate/fmt/Cargo.toml
index a6167193d..0b31abacb 100644
--- a/crate/fmt/Cargo.toml
+++ b/crate/fmt/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/params/Cargo.toml b/crate/params/Cargo.toml
index 1f6d10174..62cd5e3de 100644
--- a/crate/params/Cargo.toml
+++ b/crate/params/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/params_derive/Cargo.toml b/crate/params_derive/Cargo.toml
index 7c741854d..ad479bfcd 100644
--- a/crate/params_derive/Cargo.toml
+++ b/crate/params_derive/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
proc-macro = true
doctest = false
diff --git a/crate/resources/Cargo.toml b/crate/resources/Cargo.toml
index 0bd09b7fd..cba2e8fe8 100644
--- a/crate/resources/Cargo.toml
+++ b/crate/resources/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/rt/Cargo.toml b/crate/rt/Cargo.toml
index fed3c3d84..34c82bcd6 100644
--- a/crate/rt/Cargo.toml
+++ b/crate/rt/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
@@ -22,6 +25,7 @@ cfg-if = { workspace = true }
fn_graph = { workspace = true }
futures = { workspace = true }
miette = { workspace = true, optional = true }
+own = { workspace = true }
peace_cfg = { workspace = true }
peace_cmd_model = { workspace = true }
peace_cmd = { workspace = true }
diff --git a/crate/rt/src/cmds/clean_cmd.rs b/crate/rt/src/cmds/clean_cmd.rs
index df42be203..2cde8f007 100644
--- a/crate/rt/src/cmds/clean_cmd.rs
+++ b/crate/rt/src/cmds/clean_cmd.rs
@@ -39,8 +39,8 @@ where
/// The grouping of item functions run for a `Clean` execution to work
/// is as follows:
///
- /// 1. Run [`StatesDiscoverCmd::current`] for all `Item`s in the
- /// *forward* direction.
+ /// 1. Run [`StatesDiscoverCmd::current`] for all `Item`s in the *forward*
+ /// direction.
///
/// This populates `resources` with `Current`, needed for
/// `Item::try_state_current` during `ItemRt::clean_prepare`.
@@ -116,8 +116,8 @@ where
/// The grouping of item functions run for a `Clean` execution to work
/// is as follows:
///
- /// 1. Run [`StatesDiscoverCmd::current`] for all `Item`s in the
- /// *forward* direction.
+ /// 1. Run [`StatesDiscoverCmd::current`] for all `Item`s in the *forward*
+ /// direction.
///
/// This populates `resources` with `Current`, needed for
/// `Item::try_state_current` during `ItemRt::clean_prepare`.
diff --git a/crate/rt_model/Cargo.toml b/crate/rt_model/Cargo.toml
index 20a4223f3..783bfb6c7 100644
--- a/crate/rt_model/Cargo.toml
+++ b/crate/rt_model/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/rt_model/src/outcomes/item_apply_partial.rs b/crate/rt_model/src/outcomes/item_apply_partial.rs
index ec13d72c3..8747a5100 100644
--- a/crate/rt_model/src/outcomes/item_apply_partial.rs
+++ b/crate/rt_model/src/outcomes/item_apply_partial.rs
@@ -21,7 +21,7 @@ use crate::outcomes::ItemApplyPartialRt;
///
/// 2. Each function call *may* fail.
/// 3. If we have an enum representing the state after each function call, we
-/// have to duplicate the earlier fields per variant.
+/// have to duplicate the earlier fields per variant.
///
/// It is not likely to be error prone or too unergonomic to store each field as
/// optional.
diff --git a/crate/rt_model_core/Cargo.toml b/crate/rt_model_core/Cargo.toml
index 785882369..bef26ec17 100644
--- a/crate/rt_model_core/Cargo.toml
+++ b/crate/rt_model_core/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/rt_model_hack/Cargo.toml b/crate/rt_model_hack/Cargo.toml
index fd2dcb3cc..b03cad501 100644
--- a/crate/rt_model_hack/Cargo.toml
+++ b/crate/rt_model_hack/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/rt_model_native/Cargo.toml b/crate/rt_model_native/Cargo.toml
index 41eaeabe0..369a3e04d 100644
--- a/crate/rt_model_native/Cargo.toml
+++ b/crate/rt_model_native/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/rt_model_web/Cargo.toml b/crate/rt_model_web/Cargo.toml
index 5029f8198..fab6e9e57 100644
--- a/crate/rt_model_web/Cargo.toml
+++ b/crate/rt_model_web/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/static_check_macros/Cargo.toml b/crate/static_check_macros/Cargo.toml
index e480fb53e..b8e4c3d08 100644
--- a/crate/static_check_macros/Cargo.toml
+++ b/crate/static_check_macros/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
proc-macro = true
doctest = true
diff --git a/crate/value_traits/Cargo.toml b/crate/value_traits/Cargo.toml
index 3d5f4bb06..be1a2b14b 100644
--- a/crate/value_traits/Cargo.toml
+++ b/crate/value_traits/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/crate/webi/Cargo.toml b/crate/webi/Cargo.toml
index bc7ec5c90..0fd9473e0 100644
--- a/crate/webi/Cargo.toml
+++ b/crate/webi/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/crate/webi_components/Cargo.toml b/crate/webi_components/Cargo.toml
index b3ec4e36a..cdbcb53a0 100644
--- a/crate/webi_components/Cargo.toml
+++ b/crate/webi_components/Cargo.toml
@@ -12,12 +12,15 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
[dependencies]
-dot_ix = { workspace = true, features = ["rt", "web_components"] }
+dot_ix = { workspace = true, features = ["rt", "web_components", "flex_diag"] }
leptos = { workspace = true }
leptos_meta = { workspace = true }
leptos_router = { workspace = true }
diff --git a/crate/webi_components/src/flow_graph.rs b/crate/webi_components/src/flow_graph.rs
index 5499b1761..1809031b3 100644
--- a/crate/webi_components/src/flow_graph.rs
+++ b/crate/webi_components/src/flow_graph.rs
@@ -1,6 +1,9 @@
-use dot_ix::{model::common::DotSrcAndStyles, web_components::DotSvg};
+use dot_ix::{
+ model::{common::DotSrcAndStyles, info_graph::InfoGraph},
+ web_components::{DotSvg, FlexDiag},
+};
use leptos::{
- component, server_fn::error::NoCustomError, view, IntoView, ServerFnError, SignalGet,
+ component, server_fn::error::NoCustomError, view, IntoView, ServerFnError, Signal, SignalGet,
Transition,
};
@@ -19,23 +22,26 @@ pub fn FlowGraph() -> impl IntoView {
Some(progress_dot_graph)
};
- let outcome_dot_resource = leptos::create_resource(
+ let outcome_info_graph_resource = leptos::create_resource(
|| (),
- move |()| async move { outcome_dot_graph().await.unwrap() },
+ move |()| async move { outcome_info_graph().await.unwrap() },
);
- let outcome_dot_graph = move || {
- let outcome_dot_graph = outcome_dot_resource
- .get()
- .expect("Expected `outcome_dot_graph` to always be generated successfully.");
+ let outcome_info_graph = move || {
+ let outcome_info_graph =
+ Signal::from(move || outcome_info_graph_resource.get().unwrap_or_default());
- Some(outcome_dot_graph)
+ view! {
+
+ }
};
view! {
"Loading graph..."
}>
-
-
+
+ {outcome_info_graph}
}
@@ -63,11 +69,7 @@ pub async fn progress_dot_graph() -> Result Result> {
- use dot_ix::{
- model::common::{graphviz_dot_theme::GraphStyle, GraphvizDotTheme},
- rt::IntoGraphvizDotSrc,
- };
+pub async fn outcome_info_graph() -> Result> {
use peace_flow_model::FlowSpecInfo;
let flow_spec_info = leptos::use_context::().ok_or_else(|| {
@@ -75,8 +77,5 @@ pub async fn outcome_dot_graph() -> Result,
@@ -50,74 +45,9 @@ impl WebiOutput {
let Self {
socket_addr,
flow_spec_info,
- } = self;
-
- // Setting this to None means we'll be using cargo-leptos and its env vars
- let conf = leptos::get_configuration(None).await.unwrap();
- let leptos_options = conf.leptos_options;
- let socket_addr = socket_addr.unwrap_or(leptos_options.site_addr);
- let routes = leptos_axum::generate_route_list(move || view! { });
-
- stream::iter(crate::assets::ASSETS.iter())
- .map(Result::<_, WebiError>::Ok)
- .try_for_each(|(path_str, contents)| async move {
- let asset_path = Path::new(path_str);
- if let Some(parent_dir) = asset_path.parent() {
- tokio::fs::create_dir_all(parent_dir)
- .await
- .map_err(|error| WebiError::AssetDirCreate {
- asset_dir: parent_dir.to_path_buf(),
- error,
- })?;
- }
-
- tokio::fs::write(asset_path, contents)
- .await
- .map_err(|error| WebiError::AssetWrite {
- asset_path: asset_path.to_path_buf(),
- error,
- })?;
-
- Ok(())
- })
- .await?;
-
- let flow_spec_info = flow_spec_info.clone();
- let router = Router::new()
- // serve the pkg directory
- .nest_service(
- "/pkg",
- ServeDir::new(Path::new(leptos_options.site_pkg_dir.as_str())),
- )
- // serve the `webi` directory
- .nest_service("/webi", ServeDir::new(Path::new("webi")))
- // serve the SSR rendered homepage
- .leptos_routes_with_context(
- &leptos_options,
- routes,
- move || leptos::provide_context(flow_spec_info.clone()),
- move || view! { },
- )
- .with_state(leptos_options);
+ } = self.clone();
- let listener = tokio::net::TcpListener::bind(socket_addr)
- .await
- .unwrap_or_else(|e| panic!("Failed to listen on {socket_addr}. Error: {e}"));
- let (Ok(()) | Err(_)) = tokio::io::stderr()
- .write_all(format!("listening on http://{}\n", socket_addr).as_bytes())
- .await;
- let (Ok(()) | Err(_)) = tokio::io::stderr()
- .write_all(
- format!(
- "working dir: {}\n",
- std::env::current_dir().unwrap().display()
- )
- .as_bytes(),
- )
- .await;
- axum::serve(listener, router)
- .await
- .map_err(|error| WebiError::ServerServe { socket_addr, error })
+ WebiServer::new(socket_addr, flow_spec_info).start().await
}
}
diff --git a/crate/webi_output/src/webi_server.rs b/crate/webi_output/src/webi_server.rs
new file mode 100644
index 000000000..0003c6e7a
--- /dev/null
+++ b/crate/webi_output/src/webi_server.rs
@@ -0,0 +1,105 @@
+use std::{fmt::Debug, net::SocketAddr, path::Path};
+
+use axum::Router;
+use futures::stream::{self, StreamExt, TryStreamExt};
+use leptos::view;
+use leptos_axum::LeptosRoutes;
+use peace_flow_model::FlowSpecInfo;
+use peace_webi_components::Home;
+use peace_webi_model::WebiError;
+use tokio::io::AsyncWriteExt;
+use tower_http::services::ServeDir;
+
+/// An `OutputWrite` implementation that writes to web elements.
+#[derive(Clone, Debug)]
+pub struct WebiServer {
+ /// IP address and port to listen on.
+ socket_addr: Option,
+ /// Flow to display to the user.
+ flow_spec_info: FlowSpecInfo,
+}
+
+impl WebiServer {
+ pub fn new(socket_addr: Option, flow_spec_info: FlowSpecInfo) -> Self {
+ Self {
+ socket_addr,
+ flow_spec_info,
+ }
+ }
+}
+
+impl WebiServer {
+ pub async fn start(&mut self) -> Result<(), WebiError> {
+ let Self {
+ socket_addr,
+ flow_spec_info,
+ } = self;
+
+ // Setting this to None means we'll be using cargo-leptos and its env vars
+ let conf = leptos::get_configuration(None).await.unwrap();
+ let leptos_options = conf.leptos_options;
+ let socket_addr = socket_addr.unwrap_or(leptos_options.site_addr);
+ let routes = leptos_axum::generate_route_list(move || view! { });
+
+ stream::iter(crate::assets::ASSETS.iter())
+ .map(Result::<_, WebiError>::Ok)
+ .try_for_each(|(path_str, contents)| async move {
+ let asset_path = Path::new(path_str);
+ if let Some(parent_dir) = asset_path.parent() {
+ tokio::fs::create_dir_all(parent_dir)
+ .await
+ .map_err(|error| WebiError::AssetDirCreate {
+ asset_dir: parent_dir.to_path_buf(),
+ error,
+ })?;
+ }
+
+ tokio::fs::write(asset_path, contents)
+ .await
+ .map_err(|error| WebiError::AssetWrite {
+ asset_path: asset_path.to_path_buf(),
+ error,
+ })?;
+
+ Ok(())
+ })
+ .await?;
+
+ let flow_spec_info = flow_spec_info.clone();
+ let router = Router::new()
+ // serve the pkg directory
+ .nest_service(
+ "/pkg",
+ ServeDir::new(Path::new(leptos_options.site_pkg_dir.as_str())),
+ )
+ // serve the `webi` directory
+ .nest_service("/webi", ServeDir::new(Path::new("webi")))
+ // serve the SSR rendered homepage
+ .leptos_routes_with_context(
+ &leptos_options,
+ routes,
+ move || leptos::provide_context(flow_spec_info.clone()),
+ move || view! { },
+ )
+ .with_state(leptos_options);
+
+ let listener = tokio::net::TcpListener::bind(socket_addr)
+ .await
+ .unwrap_or_else(|e| panic!("Failed to listen on {socket_addr}. Error: {e}"));
+ let (Ok(()) | Err(_)) = tokio::io::stderr()
+ .write_all(format!("listening on http://{}\n", socket_addr).as_bytes())
+ .await;
+ let (Ok(()) | Err(_)) = tokio::io::stderr()
+ .write_all(
+ format!(
+ "working dir: {}\n",
+ std::env::current_dir().unwrap().display()
+ )
+ .as_bytes(),
+ )
+ .await;
+ axum::serve(listener, router)
+ .await
+ .map_err(|error| WebiError::ServerServe { socket_addr, error })
+ }
+}
diff --git a/crate/webi_rt/Cargo.toml b/crate/webi_rt/Cargo.toml
new file mode 100644
index 000000000..9a95bd4f5
--- /dev/null
+++ b/crate/webi_rt/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "peace_webi_rt"
+description = "Web interface runtime data types for the peace automation framework."
+documentation = "https://docs.rs/peace_webi_rt/"
+version.workspace = true
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+repository.workspace = true
+readme.workspace = true
+categories.workspace = true
+keywords.workspace = true
+license.workspace = true
+
+[lints]
+workspace = true
+
+[dependencies]
diff --git a/crate/webi_rt/src/lib.rs b/crate/webi_rt/src/lib.rs
new file mode 100644
index 000000000..14cf729e3
--- /dev/null
+++ b/crate/webi_rt/src/lib.rs
@@ -0,0 +1 @@
+//! Web interface runtime data types for the peace automation framework.
diff --git a/doc/src/technical_concepts/diagrams/outcome.md b/doc/src/technical_concepts/diagrams/outcome.md
index e4cd517f2..3ddead810 100644
--- a/doc/src/technical_concepts/diagrams/outcome.md
+++ b/doc/src/technical_concepts/diagrams/outcome.md
@@ -17,6 +17,469 @@ To render the outcome diagram, we need to deduce the physical things from `Item`
As of 2024-02-18, `Item::Params` is a single type, which would take in both **source** and **destination** parameters, so we cannot (realistically) determine the source/destination/host/cloud from the `Item::Params` type.
+### Source and Destination
+
+An `Item` is actually a step that encapsulates:
+
+1. Source location.
+2. Destination location.
+
+This can be further broken down into:
+
+```rust ,ignore
+/// Can be source / destination
+enum ItemLocation {
+ File {
+ host: Host,
+ path: PathBuf,
+ },
+ Cloud {
+ cloud_provider: CloudProvider,
+ global_or_region: GlobalOrRegion,
+ subnet: Option,
+ url: URL,
+ name: String,
+ },
+}
+```
+
+Instead of using a flat enum, we may want to use a fixed set of data structures for simplicity, or a `trait` for extensible implementations.
+
+Data structure option
+
+```rust ,ignore
+enum Realm {
+ Host {
+ address: String,
+ port: Option,
+ },
+ Cloud {
+ cloud_provider: CloudProvider,
+ global_or_region: GlobalOrRegion,
+ subnet: Option,
+ url: URL,
+ name: String,
+ },
+}
+
+struct ItemLocation {
+ /// Host or Cloud provider
+ realm: Realm,
+ /// Not necessarily a file path, but segments denoting hierarchy
+ path: Option,
+}
+```
+
+
+
+Trait option
+
+```rust ,ignore
+trait Name {
+ fn realm(&self) -> Realm;
+}
+```
+
+
+
+Note that we want to support nesting, e.g. an application server is "just a host", which may be nested within a network, or a cloud provider, or nothing.
+
+How should we do the nesting:
+
+1. Strictly defined levels, implementor selects:
+
+ 1. Cloud
+ 2. Availability Zone
+ 3. Network
+ 4. Subnet
+ 5. Host
+ 6. Path
+
+2. Arbitrary levels, levels are not necessarily defined by network-hierarchy.
+
+ Note: This doesn't allow consistency across item implementations, or, it requires the tool developer to pass the level into the item.
+
+ Actually, what we can do is:
+
+ 1. Allow the item implementor to specify the list of parents that this item resides in.
+ 2. Each parent may be an arbitrary layer around the current item.
+ 3. The peace framework will have a `struct Layer(IndexMap);` -- this is essentially `NodeHierarchy` from `dot_ix`.
+ 4. When the `LayerId`s from different items match up, those are inserted into this map.
+ 5. When we render, we render layer by layer as the hierarchy.
+
+### What we want
+
+1. Tool developer passes in parameters for the item.
+2. The correct realm for the item is automatically deduced.
+
+e.g.
+
+#### Tool Developer
+
+```rust ,ignore
+let file_download_params_spec = FileDownloadParams::new(..).into();
+```
+
+#### Item Implementor
+
+File Download
+
+```rust ,ignore
+impl Item for FileDownload {
+ fn location_from(
+ params_partial: & as Params>::Partial,
+ data: Self::Data<'_>,
+ ) -> Vec {
+ let host = params_partial
+ .src()
+ .map(Url::host)
+ .map(Host::to_owned);
+ let port = params_partial
+ .src()
+ .map(Url::port_or_known_default);
+ let url = params_partial.src();
+
+ let mut item_locations = Vec::new();
+ if let Some(host) = host {
+ item_locations.push(ItemLocation::Server { host, port });
+
+ if let Some(url) = url {
+ // May be rendered using the last segment of the URL as the node name.
+ // The full URL may be used as the tooltip.
+ item_locations.push(ItemLocation::Url(url));
+ }
+ }
+
+ item_locations
+ }
+
+ fn location_to(params: & as Params>::Partial) -> Vec {
+ let path = params_partial
+ .dest()
+ .map(Path::to_string_lossy)
+ .map(Cow::to_owned);
+
+ vec![
+ ItemLocation::Localhost,
+ ItemLocation::Path(path),
+ ]
+ }
+}
+```
+
+
+
+S3Bucket
+
+```rust ,ignore
+impl Item for S3Bucket {
+ fn location_from(
+ params_partial: & as Params>::Partial,
+ data: Self::Data<'_>,
+ ) -> Vec {
+ vec![ItemLocation::Localhost]
+ }
+
+ fn location_to(
+ params: & as Params>::Partial,
+ data: Self::Data<'_>,
+ ) -> Vec {
+ let region = data.region();
+ let availability_zone = params.availability_zone();
+ let name = params.name();
+
+ let mut item_locations = Vec::with_capacity(10);
+ item_locations.push(ItemLocation::CloudProvider(CloudProvider::Aws));
+ item_locations.push(ItemLocation::Group(region.to_string()));
+
+ if let Some(availability_zone) = availability_zone {
+ item_locations.push(ItemLocation::Group(availability_zone.to_string()));
+ if let Some(name) = name {
+ item_locations.push(ItemLocation::Name(name.to_string()));
+ }
+ }
+ }
+}
+```
+
+
+
+
+#### Framework Maintainer
+
+Go through all items' `Item::location_*` and add to outcome diagram -- see `flow_spec_info.rs`.
+
+
+### Problems
+
+#### A: How do we get items to be consistent with the item locations they publish?
+
+Cloud provider name, region, availability zone, etc.
+
+**Options:**
+
+1. 🔴 We could provide a crate with common enums.
+
+ This requires:
+
+ 1. The framework to have knowledge of many many types, or be inaccurate.
+ 2. Item implementors to always be up to date.
+
+
+ It's a lot of maintenance, so probably not a good idea.
+
+2. 🟡 Item provides default `ItemLocation`s, developer can pass in names.
+
+ This isn't too bad, as it allows tool developers control over names of the items.
+
+ It still requires item implementors to use the same `ItemLocation` variant.
+
+ It could mean additional development burden.
+
+ - If we go with sensible defaults, then we hope that item implementors use the same conventions.
+ - Tool developers passing in names to the items is an escape hatch in case the conventions are different between item implementations.
+ - Item implementors have to take in the names instead of only default them.
+
+
+ If item implementors have consistent values for their `ItemLocation`s, then the inconsistency downside is alleviated partially.
+
+ For example, extracting the host / port from a `Url` could be offloaded to the framework:
+
+ ```rust ,ignore
+ #[derive(Debug)]
+ enum ItemLocation {
+ Server(ItemLocationServer),
+ }
+
+ struct ItemLocationServer {
+ host: Host,
+ port: Option,
+ }
+
+ impl ItemLocation {
+ fn from_url(url: &Url) -> Self {
+ Self::Url(ItemLocationUrl::from(url))
+ }
+ }
+
+ impl From<&Url> for ItemLocationServer {
+ fn from(url: &Url) -> Self {
+ let host = url
+ .map(Url::host)
+ .map(Host::to_owned);
+ let port = url
+ .map(Url::port_or_known_default);
+
+ Self { host, port }
+ }
+ }
+ ```
+
+ Item implementors will implement `Item::location_from` and `Item::location_to` like so:
+
+ ```rust ,ignore
+ impl Item for FileDownload {
+ fn location_from(
+ params_partial: & as Params>::Partial,
+ data: Self::Data<'_>,
+ ) -> Vec {
+ params_partial
+ .src()
+ .as_ref()
+ .map(|src| {
+ vec![
+ ItemLocation::from_server(src),
+ ItemLocation::from_url(src),
+ ]
+ })
+ .unwrap_or_else(Vec::new)
+ }
+
+ fn location_to(
+ params: & as Params>::Partial,
+ ) -> Vec {
+ let path = params_partial
+ .dest()
+ .map(Path::to_string_lossy)
+ .map(Cow::to_owned);
+
+ vec![
+ ItemLocation::Localhost,
+ ItemLocation::Path(path),
+ ]
+ }
+ }
+ ```
+
+
+3. 🟡 Developer specifies `ItemLocation`s (from and to) for every item.
+
+ Removes the item location inconsistency issue, but also means every tool developer has to specify item locations for every item, where this work could be commonized.
+
+ This also addresses the problem B below, where the developer has control over the level of detail.
+
+ Essentially we are placing the burden of defining the outcome diagram onto the developer.
+
+ This isn't "nice" when the developer has to extract host names from URLs (common burden).
+
+ Maybe the `Item` implementor provides a method like this:
+
+ ```rust ,ignore
+ impl Item for MyItem {
+ fn item_location_from(
+ &self,
+ level: MyItemLocationLevel,
+ params_partial: & as Params>::Partial,
+ ) -> ItemLocation {
+
+ match level {
+ MyItemLocationLevel::Server => {
+ let host = params_partial
+ .src()
+ .map(Url::host)
+ .map(Host::to_owned);
+ let port = params_partial
+ .src()
+ .map(Url::port_or_known_default);
+ ItemLocation::Server { host, port }
+ }
+ _ => todo!(),
+ }
+ }
+ }
+ ```
+
+ This interface is awkward -- we don't know the params_partial at the point of flow definition (for the developer).
+
+ It could be the developer that defines that function above, combined with framework helpers:
+
+ ```rust ,ignore
+ let my_item_locations = MyItem::item_locations_spec()
+ .with_locations_from(|my_item, params_partial| {
+ // with the `From` implementations for 2. above:
+ params_partial
+ .src()
+ .as_ref()
+ .map(|src| {
+ vec![
+ ItemLocation::from_server(src),
+ ItemLocation::from_url(src),
+ ]
+ })
+ .unwrap_or_else(Vec::new)
+ })
+ .with_locations_to(todo!("similar to above"));
+ ```
+
+4. 🔴 Magically infer based on parameter names.
+
+ Too inaccurate.
+
+5. 🔴 Item implementors use a derive proc-macro.
+
+ Too many annotations -- probably easier to write the trait directly.
+
+
+#### B: How does control over whether a group is drawn get defined?
+
+1. Users may not want so many levels of detail -- it can be overwhelming.
+2. Developers may want sensible defaults / not require them to set whether a group is drawn.
+3. Developers may want to set whether a group is drawn.
+
+**Options:**
+
+1. 🟡 They can't, everything is always shown.
+
+ Not the best user experience -- too much detail can overwhelm.
+
+2. 🟡 Item implementor guidelines to not include too many layers.
+
+ May be okay? It means either we have too much / too little information sometimes.
+
+ Perhaps this is diminishing returns, and it doesn't matter too much.
+
+3. 🟡 Developer specifies `ItemLocation`s (from and to) for every item.
+
+ Same as **A:3** above.
+
+4. 🟡 Item takes in parameter whether each layer is visible.
+
+ Probably in the `Item` constructor, so we introduce a compilation error:
+
+ ```rust ignore
+ fn new(
+ /* existing params */
+ #[cfg(feature = "web")]
+ layer_visibility: MyItemLayerVisibility,
+ ) -> Self { /* .. */ }
+
+ struct MyItemLayerVisibility {
+ cloud: bool,
+ availability_zone: bool,
+ subnet: bool,
+ }
+ ```
+
+ In tandem with **A:2** above, maybe it's not worth the complexity.
+
+5. 🟡 Draw everything, developer provides separate information for layers.
+
+ 1. Probably want the `Item` to export what layers it draws.
+ 2. Developer passes a `Map` to the framework.
+
+
+ Feels weird / unintuitive as a design, not too weird as a user: "I see everything, I want to turn that one off.".
+
+
+#### C: Consistent Diagram Layout
+
+If the `ItemLocation`s changes, such as the number of `ItemLocation`s change (hierarchy level change), or the `ItemLocation` variants change (different rendering style applied), then the layout of the diagram can change:
+
+1. Position of each box can change: pushing what used to be "here", "there".
+2. Width / height of each box can expand: it doesn't fit in the screen.
+3. Colours can change: different `ItemLocation` type.
+4. Edges can change position.
+
+It can be confusing to follow if these keep changing, which is counter productive to the intent of communicating clearly which physical systems are interacting.
+
+**Options:**
+
+1. 🟡 Don't solve it now, we don't know how much of a problem it is.
+
+ `dot_ix`'s HTML `DivDiag` is not very mature anyway. We may end up developing this a lot more.
+
+ This is taking a bet that we won't have to do a large refactor to the Item API later. Probably alright since there aren't any consumers of Peace just yet.
+
+2. 🔴 Try and match nodes, and animate.
+
+ Too magic / inaccurate?
+
+3. 🟡 Require / request `Item` implementors to always provide the same number of `ItemLocation`s.
+
+ May mean every `ItemLocation` that is unknown, is still populated:
+
+ ```rust ,ignore
+ let item_location_server = item_location_server.unwrap_or(ItemLocation::ServerUnknown);
+ let item_location_url = item_location_url.unwrap_or(ItemLocation::UrlUnknown);
+
+ vec![
+ item_location_server,
+ item_location_url,
+ ]
+ ```
+
+### Solution
+
+We'll go with:
+
+* **A:2:** Item implementors provide `ItemLocation`s
+* **B:1:** Everything is shown.
+
+ There is still the possibility to migrate to **B:4** (`Item`s take in visibility flags) or **B:5** (developers pass in visibility to framework) later.
+
+* **C:1:** Don't solve the consistent diagram layout now.
+
+
## What Rendering Makes Sense
Conceptually, `Item`s can be thought of either an edge or a node:
@@ -60,3 +523,72 @@ then what is happening becomes slightly clearer:
1. There is only one level of detail.
2. It is useful to have expandable detail, e.g. hide a full URL, and allow the user to expand it if they need to.
3. It is useful to show and hide animated edges while that step is in progress.
+
+
+Old idea for code
+
+#### Item Implementor
+
+File Download
+
+```rust ,ignore
+impl Item for FileDownload {
+ fn location_from(&self, params_partial: & as Params>::Partial)
+ -> ItemLocation {
+ let address = params_partial
+ .src()
+ .map(Url::host_str)
+ .unwrap_or("")
+ .to_string();
+ let path = params_partial
+ .src()
+ .map(Url::path);
+
+ ItemLocation {
+ realm: Realm::Host { address },
+ path,
+ }
+ }
+
+ fn location_to(&self, params: & as Params>::Partial) -> ItemLocation {
+ let address = "localhost".to_string();
+ let path = params_partial
+ .dest()
+ .map(Path::to_string_lossy)
+ .map(Cow::to_owned);
+
+ ItemLocation {
+ realm: Realm::Host { address },
+ path,
+ }
+ }
+}
+```
+
+
+
+S3Bucket
+
+```rust ,ignore
+impl Item for S3Bucket {
+ fn location_from(&self, params_partial: & as Params>::Partial)
+ -> ItemLocation {
+ let address = "localhost"; // or None
+ ItemLocation::Host { address }
+ }
+
+ fn location_to(&self, params: & as Params>::Partial) -> ItemLocation {
+ ItemLocation::Cloud {
+ cloud_provider: CloudProvider::Aws,
+ global_or_region: GlobalOrRegion::Region(Region::ApSoutheast2),
+ subnet: None,
+ url: URL::from(".."),
+ name: params.name.unwrap_or(""),
+ }
+ }
+}
+```
+
+
+
+
diff --git a/examples/download/src/lib.rs b/examples/download/src/lib.rs
index ac50cc643..7b952f929 100644
--- a/examples/download/src/lib.rs
+++ b/examples/download/src/lib.rs
@@ -83,9 +83,10 @@ where
O: OutputWrite,
{
let WorkspaceAndFlow { workspace, flow } = workspace_and_flow;
- let mut cmd_ctx_builder = CmdCtx::builder_single_profile_single_flow(output, workspace)
- .with_profile(profile)
- .with_flow(flow);
+ let mut cmd_ctx_builder =
+ CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
+ .with_profile(profile)
+ .with_flow(flow);
if let Some(file_download_params) = file_download_params {
cmd_ctx_builder = cmd_ctx_builder.with_item_params::>(
diff --git a/examples/envman/Cargo.toml b/examples/envman/Cargo.toml
index 1d95706ea..852302b4b 100644
--- a/examples/envman/Cargo.toml
+++ b/examples/envman/Cargo.toml
@@ -29,7 +29,7 @@ derivative = { version = "2.2.0", optional = true }
futures = { version = "0.3.30", optional = true }
md5-rs = { version = "0.1.5", optional = true } # WASM compatible, and reads bytes as stream
peace = { path = "../..", default-features = false }
-peace_items = { path = "../../items", features = ["file_download", "tar_x"] }
+peace_items = { path = "../../items", features = ["file_download"] }
semver = { version = "1.0.22", optional = true }
serde = { version = "1.0.197", features = ["derive"] }
thiserror = { version = "1.0.57", optional = true }
diff --git a/examples/envman/src/cmds/app_upload_cmd.rs b/examples/envman/src/cmds/app_upload_cmd.rs
index 0e151406d..5ebcb9ab5 100644
--- a/examples/envman/src/cmds/app_upload_cmd.rs
+++ b/examples/envman/src/cmds/app_upload_cmd.rs
@@ -58,8 +58,10 @@ impl AppUploadCmd {
.build();
let mut cmd_ctx = {
- let cmd_ctx_builder =
- CmdCtx::builder_single_profile_single_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_single_profile_single_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
cmd_ctx_builder
@@ -116,8 +118,10 @@ impl AppUploadCmd {
.build();
let mut cmd_ctx = {
- let cmd_ctx_builder =
- CmdCtx::builder_multi_profile_single_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_multi_profile_single_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
cmd_ctx_builder
diff --git a/examples/envman/src/cmds/common.rs b/examples/envman/src/cmds/common.rs
index 98dc34947..4903270f6 100644
--- a/examples/envman/src/cmds/common.rs
+++ b/examples/envman/src/cmds/common.rs
@@ -25,7 +25,8 @@ pub async fn env_man_flow(
where
O: OutputWrite,
{
- let cmd_ctx_builder = CmdCtx::builder_no_profile_no_flow::(output, workspace);
+ let cmd_ctx_builder =
+ CmdCtx::builder_no_profile_no_flow::(output.into(), workspace.into());
crate::cmds::ws_params_augment!(cmd_ctx_builder);
let cmd_ctx = cmd_ctx_builder.await?;
Ok(cmd_ctx
diff --git a/examples/envman/src/cmds/env_cmd.rs b/examples/envman/src/cmds/env_cmd.rs
index 912271c15..d4635ddf7 100644
--- a/examples/envman/src/cmds/env_cmd.rs
+++ b/examples/envman/src/cmds/env_cmd.rs
@@ -63,8 +63,10 @@ impl EnvCmd {
let CmdOpts { profile_print } = cmd_opts;
let mut cmd_ctx = {
- let cmd_ctx_builder =
- CmdCtx::builder_single_profile_single_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_single_profile_single_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::interruptibility_augment!(cmd_ctx_builder);
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
@@ -107,8 +109,10 @@ impl EnvCmd {
let flow = EnvDeployFlow::flow().await?;
let mut cmd_ctx = {
- let cmd_ctx_builder =
- CmdCtx::builder_multi_profile_single_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_multi_profile_single_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::interruptibility_augment!(cmd_ctx_builder);
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
diff --git a/examples/envman/src/cmds/profile_init_cmd.rs b/examples/envman/src/cmds/profile_init_cmd.rs
index 90dcf6864..7e8a43905 100644
--- a/examples/envman/src/cmds/profile_init_cmd.rs
+++ b/examples/envman/src/cmds/profile_init_cmd.rs
@@ -11,7 +11,7 @@ use peace::{
rt::cmds::StatesDiscoverCmd,
rt_model::{output::OutputWrite, Flow, Workspace, WorkspaceSpec},
};
-use peace_items::{file_download::FileDownloadItem, tar_x::TarXItem};
+use peace_items::file_download::FileDownloadItem;
use semver::Version;
use url::Url;
@@ -64,8 +64,10 @@ impl ProfileInitCmd {
)?;
if !profile_reinit_allowed {
- let cmd_ctx_builder =
- CmdCtx::builder_multi_profile_no_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
let cmd_ctx_result = cmd_ctx_builder.await;
@@ -88,8 +90,10 @@ impl ProfileInitCmd {
}
}
- let cmd_ctx_builder =
- CmdCtx::builder_single_profile_no_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::interruptibility_augment!(cmd_ctx_builder);
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
@@ -208,8 +212,10 @@ where
s3_object_params_spec,
} = AppUploadFlow::params(profile_to_create, slug, version, url)?;
let cmd_ctx = {
- let cmd_ctx_builder =
- CmdCtx::builder_single_profile_single_flow::(output, workspace);
+ let cmd_ctx_builder = CmdCtx::builder_single_profile_single_flow::(
+ output.into(),
+ workspace.into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
cmd_ctx_builder
@@ -242,7 +248,6 @@ where
{
let EnvDeployFlowParamsSpecs {
app_download_params_spec,
- app_extract_params_spec,
iam_policy_params_spec,
iam_role_params_spec,
instance_profile_params_spec,
@@ -250,8 +255,10 @@ where
s3_object_params_spec,
} = EnvDeployFlow::params(profile_to_create, slug, version, url)?;
let cmd_ctx = {
- let cmd_ctx_builder =
- CmdCtx::builder_single_profile_single_flow::(output, workspace);
+ let cmd_ctx_builder = CmdCtx::builder_single_profile_single_flow::(
+ output.into(),
+ workspace.into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
cmd_ctx_builder
@@ -261,7 +268,6 @@ where
item_id!("app_download"),
app_download_params_spec,
)
- .with_item_params::>(item_id!("app_extract"), app_extract_params_spec)
.with_item_params::>(
item_id!("iam_policy"),
iam_policy_params_spec,
diff --git a/examples/envman/src/cmds/profile_list_cmd.rs b/examples/envman/src/cmds/profile_list_cmd.rs
index 72453c95f..3a11de164 100644
--- a/examples/envman/src/cmds/profile_list_cmd.rs
+++ b/examples/envman/src/cmds/profile_list_cmd.rs
@@ -29,8 +29,10 @@ impl ProfileListCmd {
WorkspaceSpec::SessionStorage,
)?;
- let cmd_ctx_builder =
- CmdCtx::builder_multi_profile_no_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
let mut cmd_ctx = cmd_ctx_builder.await?;
diff --git a/examples/envman/src/cmds/profile_show_cmd.rs b/examples/envman/src/cmds/profile_show_cmd.rs
index 2e376b9e9..21c8adcc1 100644
--- a/examples/envman/src/cmds/profile_show_cmd.rs
+++ b/examples/envman/src/cmds/profile_show_cmd.rs
@@ -31,8 +31,10 @@ impl ProfileShowCmd {
WorkspaceSpec::SessionStorage,
)?;
- let cmd_ctx_builder =
- CmdCtx::builder_single_profile_no_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
let profile_key = WorkspaceParamsKey::Profile;
diff --git a/examples/envman/src/cmds/profile_switch_cmd.rs b/examples/envman/src/cmds/profile_switch_cmd.rs
index 7b007565f..e15d9bd3f 100644
--- a/examples/envman/src/cmds/profile_switch_cmd.rs
+++ b/examples/envman/src/cmds/profile_switch_cmd.rs
@@ -31,8 +31,10 @@ impl ProfileSwitchCmd {
let env_man_flow = env_man_flow(output, &workspace).await?;
- let cmd_ctx_builder =
- CmdCtx::builder_multi_profile_no_flow::(output, &workspace);
+ let cmd_ctx_builder = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ );
crate::cmds::ws_and_profile_params_augment!(cmd_ctx_builder);
let mut cmd_ctx = cmd_ctx_builder.await?;
@@ -53,8 +55,10 @@ impl ProfileSwitchCmd {
app_name,
});
} else {
- let cmd_ctx_builder =
- CmdCtx::builder_no_profile_no_flow::(output, workspace);
+ let cmd_ctx_builder = CmdCtx::builder_no_profile_no_flow::(
+ output.into(),
+ workspace.into(),
+ );
crate::cmds::ws_params_augment!(cmd_ctx_builder);
cmd_ctx_builder
.with_workspace_param_value(
diff --git a/examples/envman/src/flows/env_deploy_flow.rs b/examples/envman/src/flows/env_deploy_flow.rs
index cd936f361..5ab07d58c 100644
--- a/examples/envman/src/flows/env_deploy_flow.rs
+++ b/examples/envman/src/flows/env_deploy_flow.rs
@@ -5,10 +5,7 @@ use peace::{
params::{Params, ParamsSpec},
rt_model::{Flow, ItemGraphBuilder},
};
-use peace_items::{
- file_download::{FileDownloadItem, FileDownloadParams},
- tar_x::{TarXItem, TarXParams},
-};
+use peace_items::file_download::{FileDownloadItem, FileDownloadParams};
use semver::Version;
use url::Url;
@@ -36,7 +33,6 @@ impl EnvDeployFlow {
let [
app_download_id,
- app_extract_id,
iam_policy_item_id,
iam_role_item_id,
instance_profile_item_id,
@@ -44,7 +40,6 @@ impl EnvDeployFlow {
s3_object_id,
] = graph_builder.add_fns([
FileDownloadItem::::new(item_id!("app_download")).into(),
- TarXItem::::new(item_id!("app_extract")).into(),
IamPolicyItem::::new(item_id!("iam_policy")).into(),
IamRoleItem::::new(item_id!("iam_role")).into(),
InstanceProfileItem::::new(item_id!("instance_profile")).into(),
@@ -53,7 +48,6 @@ impl EnvDeployFlow {
]);
graph_builder.add_logic_edges([
- (app_download_id, app_extract_id),
(iam_policy_item_id, iam_role_item_id),
(iam_role_item_id, instance_profile_item_id),
// Download the file before uploading it.
@@ -81,15 +75,8 @@ impl EnvDeployFlow {
let repo_name = slug.repo_name();
let app_download_dir = PathBuf::from_iter([account, repo_name, &format!("{version}")]);
- #[cfg(target_family = "windows")]
- let file_ext = "zip";
- #[cfg(any(target_family = "unix", target_family = "wasm"))]
- let file_ext = "tar";
- // windows:
- // https://github.com/azriel91/web_app/releases/download/0.1.0/web_app.zip
- //
- // linux:
// https://github.com/azriel91/web_app/releases/download/0.1.0/web_app.tar
+ let file_ext = "tar";
let web_app_file_url = url.map(Result::Ok).unwrap_or_else(|| {
let url_candidate = format!(
"https://github.com/{account}/{repo_name}/releases/download/{version}/{repo_name}.{file_ext}"
@@ -107,10 +94,6 @@ impl EnvDeployFlow {
peace_items::file_download::StorageForm::Base64,
)
.into();
- let app_extract_params_spec = TarXParams::::field_wise_spec()
- .with_tar_path(web_app_path_local.clone())
- .with_dest(app_download_dir.join("extracted"))
- .build();
let iam_policy_name = profile.to_string();
let iam_role_name = profile.to_string();
@@ -157,7 +140,6 @@ impl EnvDeployFlow {
Ok(EnvDeployFlowParamsSpecs {
app_download_params_spec,
- app_extract_params_spec,
iam_policy_params_spec,
iam_role_params_spec,
instance_profile_params_spec,
@@ -170,7 +152,6 @@ impl EnvDeployFlow {
#[derive(Debug)]
pub struct EnvDeployFlowParamsSpecs {
pub app_download_params_spec: ParamsSpec>,
- pub app_extract_params_spec: ParamsSpec>,
pub iam_policy_params_spec: ParamsSpec>,
pub iam_role_params_spec: ParamsSpec>,
pub instance_profile_params_spec: ParamsSpec>,
diff --git a/examples/envman/src/model/envman_error.rs b/examples/envman/src/model/envman_error.rs
index e56e3c896..466c858b6 100644
--- a/examples/envman/src/model/envman_error.rs
+++ b/examples/envman/src/model/envman_error.rs
@@ -84,14 +84,6 @@ pub enum EnvManError {
#[from]
peace_items::file_download::FileDownloadError,
),
- /// A `TarX` item error occurred.
- #[error("A `TarX` item error occurred.")]
- PeaceItemTarX(
- #[cfg_attr(feature = "error_reporting", diagnostic_source)]
- #[source]
- #[from]
- peace_items::tar_x::TarXError,
- ),
/// An `InstanceProfile` item error occurred.
#[error("An `InstanceProfile` item error occurred.")]
InstanceProfileItem(
diff --git a/examples/envman/src/output.rs b/examples/envman/src/output.rs
index 275ffc729..0f0580fdc 100644
--- a/examples/envman/src/output.rs
+++ b/examples/envman/src/output.rs
@@ -17,7 +17,7 @@ where
O: OutputWrite,
{
output
- .present(&Heading::new(HeadingLevel::Level1, "Errors"))
+ .present(Heading::new(HeadingLevel::Level1, "Errors"))
.await?;
#[cfg(feature = "error_reporting")]
@@ -73,7 +73,7 @@ where
O: OutputWrite,
{
output
- .present(&Heading::new(HeadingLevel::Level1, "Errors"))
+ .present(Heading::new(HeadingLevel::Level1, "Errors"))
.await?;
#[cfg(feature = "error_reporting")]
diff --git a/items/Cargo.toml b/items/Cargo.toml
index da6a0281b..6c1caf9e0 100644
--- a/items/Cargo.toml
+++ b/items/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[package.metadata.docs.rs]
all-features = true
diff --git a/items/blank/Cargo.toml b/items/blank/Cargo.toml
index c6c45ec55..f01748a3f 100644
--- a/items/blank/Cargo.toml
+++ b/items/blank/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/items/file_download/Cargo.toml b/items/file_download/Cargo.toml
index b392689d0..25f02951c 100644
--- a/items/file_download/Cargo.toml
+++ b/items/file_download/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/items/sh_cmd/Cargo.toml b/items/sh_cmd/Cargo.toml
index 7ac1dcc9d..7d3ab4573 100644
--- a/items/sh_cmd/Cargo.toml
+++ b/items/sh_cmd/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = true
test = false
diff --git a/items/tar_x/Cargo.toml b/items/tar_x/Cargo.toml
index 00ae4bba1..da6e95a4c 100644
--- a/items/tar_x/Cargo.toml
+++ b/items/tar_x/Cargo.toml
@@ -12,6 +12,9 @@ categories.workspace = true
keywords.workspace = true
license.workspace = true
+[lints]
+workspace = true
+
[lib]
doctest = false
test = false
diff --git a/workspace_tests/Cargo.toml b/workspace_tests/Cargo.toml
index 334e438f6..ed2f785bd 100644
--- a/workspace_tests/Cargo.toml
+++ b/workspace_tests/Cargo.toml
@@ -13,6 +13,9 @@ keywords.workspace = true
license.workspace = true
publish = false
+[lints]
+workspace = true
+
[lib]
doctest = false
test = true
diff --git a/workspace_tests/src/cmd/ctx/cmd_ctx.rs b/workspace_tests/src/cmd/ctx/cmd_ctx.rs
index 1be308690..0a4bc4653 100644
--- a/workspace_tests/src/cmd/ctx/cmd_ctx.rs
+++ b/workspace_tests/src/cmd/ctx/cmd_ctx.rs
@@ -14,8 +14,8 @@ async fn single_profile_single_flow_getters() -> Result<(), Box::new(flow_id.clone(), ItemGraphBuilder::new().build());
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtxBuilder::single_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtxBuilder::single_profile_single_flow(output.into(), (&workspace).into())
.with_profile(profile.clone())
.with_flow(&flow)
.build()
diff --git a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_no_flow_builder.rs b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_no_flow_builder.rs
index 880f17e60..cbf2c2b1e 100644
--- a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_no_flow_builder.rs
+++ b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_no_flow_builder.rs
@@ -22,11 +22,13 @@ async fn build() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_multi_profile_no_flow::(&mut output, &workspace)
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let (profile_dirs, profile_history_dirs) = {
@@ -70,16 +72,18 @@ async fn build_with_workspace_params() -> Result<(), Box>
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_multi_profile_no_flow::(&mut output, &workspace)
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let (profile_dirs, profile_history_dirs) = {
@@ -129,14 +133,16 @@ async fn build_with_profile_params() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_multi_profile_no_flow::(&mut output, &workspace)
- .with_profile_params_k::()
- .with_profile_param::(String::from("profile_param_0"))
- .with_profile_param::(String::from("profile_param_1"))
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile_params_k::()
+ .with_profile_param::(String::from("profile_param_0"))
+ .with_profile_param::(String::from("profile_param_1"))
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let (profile_dirs, profile_history_dirs) = {
@@ -181,19 +187,21 @@ async fn build_with_workspace_params_with_profile_params() -> Result<(), Box(&mut output, &workspace)
- .with_profile_params_k::()
- .with_profile_param::(String::from("profile_param_0"))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_profile_param::(String::from("profile_param_1"))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile_params_k::()
+ .with_profile_param::(String::from("profile_param_0"))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_profile_param::(String::from("profile_param_1"))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let (profile_dirs, profile_history_dirs) = {
@@ -250,17 +258,19 @@ async fn build_with_workspace_params_with_profile_filter() -> Result<(), Box(&mut output, &workspace)
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .with_profile_filter(|profile| **profile == "test_profile")
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .with_profile_filter(|profile| **profile == "test_profile")
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let (profile_dirs, profile_history_dirs) = {
@@ -306,20 +316,22 @@ async fn build_with_workspace_params_with_profile_params_with_profile_filter()
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_multi_profile_no_flow::(&mut output, &workspace)
- .with_profile_params_k::()
- .with_profile_param::(String::from("profile_param_0"))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_profile_param::(String::from("profile_param_1"))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .with_profile_filter(|profile| **profile == "test_profile")
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile_params_k::()
+ .with_profile_param::(String::from("profile_param_0"))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_profile_param::(String::from("profile_param_1"))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .with_profile_filter(|profile| **profile == "test_profile")
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let (profile_dirs, profile_history_dirs) = {
@@ -371,11 +383,13 @@ async fn list_profile_dirs_invalid_profile_name() -> Result<(), Box(&mut output, &workspace)
- .build()
- .await;
+ let output = NoOpOutput;
+ let cmd_ctx_result = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .build()
+ .await;
let profile_other_dir = ProfileDir::from((workspace.dirs().peace_app_dir(), &profile_other));
({
@@ -419,11 +433,13 @@ async fn getters() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx =
- CmdCtx::builder_multi_profile_no_flow::(&mut output, &workspace)
- .build()
- .await?;
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .build()
+ .await?;
assert_eq!(workspace.dirs().workspace_dir(), cmd_ctx.workspace_dir());
assert_eq!(workspace.dirs().peace_dir(), cmd_ctx.peace_dir());
@@ -448,11 +464,13 @@ async fn debug() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx =
- CmdCtx::builder_multi_profile_no_flow::(&mut output, &workspace)
- .build()
- .await?;
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_multi_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .build()
+ .await?;
let multi_profile_no_flow = cmd_ctx.scope();
assert!(format!("{multi_profile_no_flow:?}").contains("MultiProfileNoFlow {"));
diff --git a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_single_flow_builder.rs b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_single_flow_builder.rs
index 1421074eb..50beaabdd 100644
--- a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_single_flow_builder.rs
+++ b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/multi_profile_single_flow_builder.rs
@@ -24,8 +24,8 @@ async fn build() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(output.into(), (&workspace).into())
.with_flow(&flow)
.build()
.await?;
@@ -82,8 +82,8 @@ async fn build_with_workspace_params() -> Result<(), Box>
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(output.into(), (&workspace).into())
.with_flow(&flow)
.with_workspace_param_value(String::from("profile"), Some(profile.clone()))
.with_workspace_param_value(
@@ -151,8 +151,8 @@ async fn build_with_profile_params() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(output.into(), (&workspace).into())
.with_profile_params_k::()
.with_profile_param::(String::from("profile_param_0"))
.with_profile_param::(String::from("profile_param_1"))
@@ -212,8 +212,8 @@ async fn build_with_flow_params() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(output.into(), (&workspace).into())
.with_flow(&flow)
.with_flow_params_k::()
.with_flow_param::(String::from("flow_param_0"))
@@ -280,8 +280,8 @@ async fn build_with_workspace_params_with_profile_params() -> Result<(), Box()
.with_profile_param::(String::from("profile_param_0"))
@@ -359,8 +359,8 @@ async fn build_with_workspace_params_with_profile_params_with_flow_params()
)
.await?;
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_multi_profile_single_flow(output.into(), (&workspace).into())
.with_flow(&flow)
.with_profile_params_k::()
.with_profile_param::(String::from("profile_param_0"))
@@ -447,8 +447,8 @@ async fn build_with_workspace_params_with_profile_filter() -> Result<(), Box()
.with_profile_param::(String::from("profile_param_0"))
.with_workspace_param_value(String::from("profile"), Some(profile.clone()))
@@ -592,12 +592,14 @@ async fn getters() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx =
- CmdCtx::builder_multi_profile_single_flow::(&mut output, &workspace)
- .with_flow(&flow)
- .build()
- .await?;
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_multi_profile_single_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_flow(&flow)
+ .build()
+ .await?;
assert_eq!(workspace.dirs().workspace_dir(), cmd_ctx.workspace_dir());
assert_eq!(workspace.dirs().peace_dir(), cmd_ctx.peace_dir());
@@ -633,12 +635,14 @@ async fn debug() -> Result<(), Box> {
)
.await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx =
- CmdCtx::builder_multi_profile_single_flow::(&mut output, &workspace)
- .with_flow(&flow)
- .build()
- .await?;
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_multi_profile_single_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_flow(&flow)
+ .build()
+ .await?;
let multi_profile_single_flow = cmd_ctx.scope();
assert!(format!("{multi_profile_single_flow:?}").contains("MultiProfileSingleFlow {"));
diff --git a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/no_profile_no_flow_builder.rs b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/no_profile_no_flow_builder.rs
index 2c7bf22da..c29d32585 100644
--- a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/no_profile_no_flow_builder.rs
+++ b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/no_profile_no_flow_builder.rs
@@ -10,10 +10,11 @@ async fn build() -> Result<(), Box> {
let tempdir = tempfile::tempdir()?;
let workspace = workspace(&tempdir, app_name!("test_no_profile_no_flow"))?;
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_no_profile_no_flow::(&mut output, &workspace)
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx =
+ CmdCtx::builder_no_profile_no_flow::(output.into(), (&workspace).into())
+ .build()
+ .await?;
assert!(std::ptr::eq(&workspace, cmd_ctx.workspace()));
Ok(())
@@ -25,15 +26,16 @@ async fn build_with_workspace_params() -> Result<(), Box>
let workspace = workspace(&tempdir, app_name!("test_no_profile_no_flow"))?;
let profile = profile!("test_profile");
- let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_no_profile_no_flow::(&mut output, &workspace)
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx =
+ CmdCtx::builder_no_profile_no_flow::(output.into(), (&workspace).into())
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
diff --git a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_no_flow_builder.rs b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_no_flow_builder.rs
index 7ff23c975..690266fd1 100644
--- a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_no_flow_builder.rs
+++ b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_no_flow_builder.rs
@@ -12,12 +12,14 @@ async fn build() -> Result<(), Box> {
let workspace = workspace(&tempdir, app_name!("test_single_profile_no_flow"))?;
let profile = profile!("test_profile");
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_single_profile_no_flow::(&mut output, &workspace)
- .with_profile(profile.clone())
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -38,17 +40,19 @@ async fn build_with_workspace_params() -> Result<(), Box>
let workspace = workspace(&tempdir, app_name!("test_single_profile_no_flow"))?;
let profile = profile!("test_profile");
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_single_profile_no_flow::(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -75,14 +79,16 @@ async fn build_with_profile_params() -> Result<(), Box> {
let workspace = workspace(&tempdir, app_name!("test_single_profile_no_flow"))?;
let profile = profile!("test_profile");
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_single_profile_no_flow::(&mut output, &workspace)
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_profile(profile.clone())
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_profile(profile.clone())
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -107,19 +113,21 @@ async fn build_with_workspace_params_with_profile_params() -> Result<(), Box(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -150,17 +158,19 @@ async fn build_with_workspace_params_with_profile_from_params()
let workspace = workspace(&tempdir, app_name!("test_single_profile_no_flow"))?;
let profile = profile!("test_profile");
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_single_profile_no_flow::(&mut output, &workspace)
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .with_profile_from_workspace_param(&String::from("profile"))
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .with_profile_from_workspace_param(&String::from("profile"))
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -188,19 +198,21 @@ async fn build_with_workspace_params_with_profile_params_with_profile_from_param
let workspace = workspace(&tempdir, app_name!("test_single_profile_no_flow"))?;
let profile = profile!("test_profile");
- let mut output = NoOpOutput;
- let cmd_ctx =
- CmdCtx::builder_single_profile_no_flow::(&mut output, &workspace)
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .with_profile_from_workspace_param(&String::from("profile"))
- .build()
- .await?;
+ let output = NoOpOutput;
+ let cmd_ctx = CmdCtx::builder_single_profile_no_flow::(
+ output.into(),
+ (&workspace).into(),
+ )
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .with_profile_from_workspace_param(&String::from("profile"))
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
diff --git a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_single_flow_builder.rs b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_single_flow_builder.rs
index e9b26e461..8447384de 100644
--- a/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_single_flow_builder.rs
+++ b/workspace_tests/src/cmd/ctx/cmd_ctx_builder/single_profile_single_flow_builder.rs
@@ -25,11 +25,14 @@ async fn build() -> Result<(), Box> {
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -56,16 +59,19 @@ async fn build_with_workspace_params() -> Result<(), Box>
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -103,13 +109,16 @@ async fn build_with_profile_params() -> Result<(), Box> {
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_profile(profile.clone())
- .with_flow(&flow)
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -139,13 +148,16 @@ async fn build_with_flow_params() -> Result<(), Box> {
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_flow_param_value(String::from("flow_param_0"), Some(true))
- .with_flow_param_value(String::from("flow_param_1"), Some(456u16))
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_flow_param_value(String::from("flow_param_0"), Some(true))
+ .with_flow_param_value(String::from("flow_param_1"), Some(456u16))
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -179,18 +191,21 @@ async fn build_with_workspace_params_with_profile_params() -> Result<(), Box::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -233,20 +248,23 @@ async fn build_with_workspace_params_with_profile_params_with_flow_params()
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_flow_param_value(String::from("flow_param_0"), Some(true))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_flow_param_value(String::from("flow_param_1"), Some(456u16))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_flow_param_value(String::from("flow_param_0"), Some(true))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_flow_param_value(String::from("flow_param_1"), Some(456u16))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -293,16 +311,19 @@ async fn build_with_workspace_params_with_profile_from_params()
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .with_profile_from_workspace_param(&String::from("profile"))
- .with_flow(&flow)
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .with_profile_from_workspace_param(&String::from("profile"))
+ .with_flow(&flow)
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -341,20 +362,23 @@ async fn build_with_workspace_params_with_profile_params_with_profile_from_param
let flow = Flow::::new(flow_id, ItemGraphBuilder::new().build());
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
- .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
- .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
- .with_workspace_param_value(
- String::from("ws_param_1"),
- Some("ws_param_1_value".to_string()),
- )
- .with_flow_param_value(String::from("flow_param_0"), Some(true))
- .with_profile_from_workspace_param(&String::from("profile"))
- .with_flow_param_value(String::from("flow_param_1"), Some(456u16))
- .with_flow(&flow)
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile_param_value(String::from("profile_param_0"), Some(1u32))
+ .with_workspace_param_value(String::from("profile"), Some(profile.clone()))
+ .with_profile_param_value(String::from("profile_param_1"), Some(2u64))
+ .with_workspace_param_value(
+ String::from("ws_param_1"),
+ Some("ws_param_1_value".to_string()),
+ )
+ .with_flow_param_value(String::from("flow_param_0"), Some(true))
+ .with_profile_from_workspace_param(&String::from("profile"))
+ .with_flow_param_value(String::from("flow_param_1"), Some(456u16))
+ .with_flow(&flow)
+ .build()
+ .await?;
let peace_app_dir = workspace.dirs().peace_app_dir();
let profile_dir = ProfileDir::from((peace_app_dir, &profile));
@@ -406,12 +430,15 @@ async fn build_with_item_params_returns_ok_when_params_provided()
let flow = Flow::::new(flow_id, item_graph);
let mut output = NoOpOutput;
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
+ .build()
+ .await?;
let scope = cmd_ctx.scope();
let params_specs = scope.params_specs();
@@ -452,11 +479,14 @@ async fn build_with_item_params_returns_err_when_params_not_provided_and_not_sto
let flow = Flow::::new(flow_id, item_graph);
let mut output = NoOpOutput;
- let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .build()
- .await;
+ let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .build()
+ .await;
({
#[cfg_attr(coverage_nightly, coverage(off))]
@@ -500,18 +530,24 @@ async fn build_with_item_params_returns_ok_when_params_not_provided_but_are_stor
let flow = Flow::::new(flow_id, item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
- .build()
- .await?;
-
- let cmd_ctx_from_stored = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
+ .build()
+ .await?;
+
+ let cmd_ctx_from_stored = CmdCtx::builder_single_profile_single_flow::<
+ PeaceTestError,
+ NoOpOutput,
+ >((&mut output).into(), (&workspace).into())
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .build()
+ .await?;
let scope = cmd_ctx_from_stored.scope();
let params_specs = scope.params_specs();
@@ -552,19 +588,25 @@ async fn build_with_item_params_returns_ok_and_uses_params_provided_when_params_
let flow = Flow::::new(flow_id, item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
- .build()
- .await?;
-
- let cmd_ctx_from_stored = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![2u8]).into())
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
+ .build()
+ .await?;
+
+ let cmd_ctx_from_stored = CmdCtx::builder_single_profile_single_flow::<
+ PeaceTestError,
+ NoOpOutput,
+ >((&mut output).into(), (&workspace).into())
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![2u8]).into())
+ .build()
+ .await?;
let scope = cmd_ctx_from_stored.scope();
let params_specs = scope.params_specs();
@@ -605,19 +647,25 @@ async fn build_with_item_params_returns_err_when_params_provided_mismatch()
let flow = Flow::::new(flow_id, item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
- .build()
- .await?;
-
- let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(item_id!("mismatch_id"), VecA(vec![2u8]).into())
- .build()
- .await;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
+ .build()
+ .await?;
+
+ let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(item_id!("mismatch_id"), VecA(vec![2u8]).into())
+ .build()
+ .await;
({
#[cfg_attr(coverage_nightly, coverage(off))]
@@ -669,12 +717,15 @@ async fn build_with_item_params_returns_err_when_params_stored_mismatch()
let flow = Flow::::new(flow_id.clone(), item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(item_id!("original_id"), VecA(vec![1u8]).into())
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(item_id!("original_id"), VecA(vec![1u8]).into())
+ .build()
+ .await?;
let item_graph = {
let mut item_graph_builder = ItemGraphBuilder::new();
@@ -686,12 +737,15 @@ async fn build_with_item_params_returns_err_when_params_stored_mismatch()
item_graph_builder.build()
};
let flow = Flow::::new(flow_id, item_graph);
- let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(item_id!("mismatch_id"), VecA(vec![2u8]).into())
- .build()
- .await;
+ let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(item_id!("mismatch_id"), VecA(vec![2u8]).into())
+ .build()
+ .await;
({
#[cfg_attr(coverage_nightly, coverage(off))]
@@ -743,17 +797,20 @@ async fn build_with_item_params_returns_ok_when_spec_provided_for_previous_mappi
let flow = Flow::::new(flow_id.clone(), item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(
- VecCopyItem::ID_DEFAULT.clone(),
- VecA::field_wise_spec()
- .with_0_from_map(|_: &u8| Some(vec![1u8]))
- .build(),
- )
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(
+ VecCopyItem::ID_DEFAULT.clone(),
+ VecA::field_wise_spec()
+ .with_0_from_map(|_: &u8| Some(vec![1u8]))
+ .build(),
+ )
+ .build()
+ .await?;
let item_graph = {
let mut item_graph_builder = ItemGraphBuilder::new();
@@ -761,18 +818,21 @@ async fn build_with_item_params_returns_ok_when_spec_provided_for_previous_mappi
item_graph_builder.build()
};
let flow = Flow::::new(flow_id, item_graph);
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(
- VecCopyItem::ID_DEFAULT.clone(),
- VecA::field_wise_spec()
- .with_0_from_map(|_: &u8| Some(vec![1u8]))
- .build(),
- )
- .with_flow_param_value(String::from("for_item_mapping"), Some(1u8))
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(
+ VecCopyItem::ID_DEFAULT.clone(),
+ VecA::field_wise_spec()
+ .with_0_from_map(|_: &u8| Some(vec![1u8]))
+ .build(),
+ )
+ .with_flow_param_value(String::from("for_item_mapping"), Some(1u8))
+ .build()
+ .await?;
let scope = cmd_ctx.scope();
let params_specs = scope.params_specs();
@@ -823,17 +883,20 @@ async fn build_with_item_params_returns_err_when_spec_fully_not_provided_for_pre
let flow = Flow::::new(flow_id.clone(), item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(
- VecCopyItem::ID_DEFAULT.clone(),
- VecA::field_wise_spec()
- .with_0_from_map(|_: &u8| Some(vec![1u8]))
- .build(),
- )
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(
+ VecCopyItem::ID_DEFAULT.clone(),
+ VecA::field_wise_spec()
+ .with_0_from_map(|_: &u8| Some(vec![1u8]))
+ .build(),
+ )
+ .build()
+ .await?;
let item_graph = {
let mut item_graph_builder = ItemGraphBuilder::new();
@@ -841,12 +904,15 @@ async fn build_with_item_params_returns_err_when_spec_fully_not_provided_for_pre
item_graph_builder.build()
};
let flow = Flow::::new(flow_id, item_graph);
- let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- // Note: no item_params for `VecCopyItem`
- .build()
- .await;
+ let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ // Note: no item_params for `VecCopyItem`
+ .build()
+ .await;
({
#[cfg_attr(coverage_nightly, coverage(off))]
@@ -894,17 +960,20 @@ async fn build_with_item_params_returns_err_when_value_spec_not_provided_for_pre
let flow = Flow::::new(flow_id.clone(), item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(
- VecCopyItem::ID_DEFAULT.clone(),
- VecA::field_wise_spec()
- .with_0_from_map(|_: &u8| Some(vec![1u8]))
- .build(),
- )
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(
+ VecCopyItem::ID_DEFAULT.clone(),
+ VecA::field_wise_spec()
+ .with_0_from_map(|_: &u8| Some(vec![1u8]))
+ .build(),
+ )
+ .build()
+ .await?;
let item_graph = {
let mut item_graph_builder = ItemGraphBuilder::new();
@@ -912,16 +981,19 @@ async fn build_with_item_params_returns_err_when_value_spec_not_provided_for_pre
item_graph_builder.build()
};
let flow = Flow::::new(flow_id, item_graph);
- let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- // Note: item_params provided, but not enough to replace mapping function.
- .with_item_params::(
- VecCopyItem::ID_DEFAULT.clone(),
- VecA::field_wise_spec().build(),
- )
- .build()
- .await;
+ let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ // Note: item_params provided, but not enough to replace mapping function.
+ .with_item_params::(
+ VecCopyItem::ID_DEFAULT.clone(),
+ VecA::field_wise_spec().build(),
+ )
+ .build()
+ .await;
({
#[cfg_attr(coverage_nightly, coverage(off))]
@@ -969,12 +1041,15 @@ async fn build_with_item_params_returns_params_specs_mismatch_err_when_item_rena
let flow = Flow::::new(flow_id.clone(), item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(item_id!("original_id"), VecA(vec![1u8]).into())
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(item_id!("original_id"), VecA(vec![1u8]).into())
+ .build()
+ .await?;
let item_graph = {
let mut item_graph_builder = ItemGraphBuilder::new();
@@ -983,12 +1058,15 @@ async fn build_with_item_params_returns_params_specs_mismatch_err_when_item_rena
item_graph_builder.build()
};
let flow = Flow::::new(flow_id, item_graph);
- let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(item_id!("mismatch_id"), VecA(vec![2u8]).into())
- .build()
- .await;
+ let cmd_ctx_result = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(item_id!("mismatch_id"), VecA(vec![2u8]).into())
+ .build()
+ .await;
({
#[cfg_attr(coverage_nightly, coverage(off))]
@@ -1041,11 +1119,14 @@ async fn build_with_item_params_returns_ok_when_new_item_added_with_params_provi
let flow = Flow::::new(flow_id.clone(), item_graph);
let mut output = NoOpOutput;
- let _cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .build()
- .await?;
+ let _cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .build()
+ .await?;
// Build second `cmd_ctx` with item.
let item_graph = {
@@ -1054,12 +1135,15 @@ async fn build_with_item_params_returns_ok_when_new_item_added_with_params_provi
item_graph_builder.build()
};
let flow = Flow::::new(flow_id, item_graph);
- let cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
- .with_profile(profile.clone())
- .with_flow(&flow)
- .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
- .build()
- .await?;
+ let cmd_ctx = CmdCtx::builder_single_profile_single_flow::(
+ (&mut output).into(),
+ (&workspace).into(),
+ )
+ .with_profile(profile.clone())
+ .with_flow(&flow)
+ .with_item_params::(VecCopyItem::ID_DEFAULT.clone(), VecA(vec![1u8]).into())
+ .build()
+ .await?;
let scope = cmd_ctx.scope();
let params_specs = scope.params_specs();
diff --git a/workspace_tests/src/cmd_rt/cmd_execution.rs b/workspace_tests/src/cmd_rt/cmd_execution.rs
index 375b82d67..02ddf2b30 100644
--- a/workspace_tests/src/cmd_rt/cmd_execution.rs
+++ b/workspace_tests/src/cmd_rt/cmd_execution.rs
@@ -37,8 +37,8 @@ async fn runs_one_cmd_block() -> Result<(), PeaceTestError> {
flow,
} = test_ctx_init().await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::(
@@ -94,8 +94,8 @@ async fn chains_multiple_cmd_blocks() -> Result<(), PeaceTestError> {
flow,
} = test_ctx_init().await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::(
diff --git a/workspace_tests/src/cmd_rt/cmd_execution/cmd_execution_error_builder.rs b/workspace_tests/src/cmd_rt/cmd_execution/cmd_execution_error_builder.rs
index 123ad3114..9a7044cbf 100644
--- a/workspace_tests/src/cmd_rt/cmd_execution/cmd_execution_error_builder.rs
+++ b/workspace_tests/src/cmd_rt/cmd_execution/cmd_execution_error_builder.rs
@@ -41,8 +41,8 @@ async fn builds_error_for_missing_input_tuple_first_parameter() -> Result<(), Pe
flow,
} = test_ctx_init().await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::(
@@ -130,8 +130,8 @@ async fn builds_error_for_missing_input_tuple_second_parameter() -> Result<(), P
flow,
} = test_ctx_init().await?;
- let mut output = NoOpOutput;
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = NoOpOutput;
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::(
diff --git a/workspace_tests/src/flow_model/flow_spec_info.rs b/workspace_tests/src/flow_model/flow_spec_info.rs
index 5a25a78bd..512f8ad52 100644
--- a/workspace_tests/src/flow_model/flow_spec_info.rs
+++ b/workspace_tests/src/flow_model/flow_spec_info.rs
@@ -5,10 +5,10 @@ use peace::{
dot_ix::{
self,
model::{
- common::{EdgeId, NodeHierarchy, NodeId},
+ common::{Edges, NodeHierarchy, NodeNames},
edge_id,
- info_graph::{GraphDir, InfoGraph, NodeInfo},
- node_id, IndexMap,
+ info_graph::{GraphDir, InfoGraph},
+ node_id,
},
},
FlowSpecInfo,
@@ -34,7 +34,7 @@ fn to_progress_info_graph() -> Result<(), Box> {
node_hierarchy.insert(node_id!("e"), NodeHierarchy::new());
node_hierarchy.insert(node_id!("f"), NodeHierarchy::new());
- let mut edges = IndexMap::::new();
+ let mut edges = Edges::new();
edges.insert(edge_id!("a__b"), [node_id!("a"), node_id!("b")]);
edges.insert(edge_id!("a__c"), [node_id!("a"), node_id!("c")]);
edges.insert(edge_id!("b__e"), [node_id!("b"), node_id!("e")]);
@@ -42,18 +42,18 @@ fn to_progress_info_graph() -> Result<(), Box> {
edges.insert(edge_id!("d__e"), [node_id!("d"), node_id!("e")]);
edges.insert(edge_id!("f__e"), [node_id!("f"), node_id!("e")]);
- let mut node_infos = IndexMap::::new();
- node_infos.insert(node_id!("a"), NodeInfo::new(String::from("a")));
- node_infos.insert(node_id!("b"), NodeInfo::new(String::from("b")));
- node_infos.insert(node_id!("c"), NodeInfo::new(String::from("c")));
- node_infos.insert(node_id!("d"), NodeInfo::new(String::from("d")));
- node_infos.insert(node_id!("e"), NodeInfo::new(String::from("e")));
- node_infos.insert(node_id!("f"), NodeInfo::new(String::from("f")));
+ let mut node_names = NodeNames::new();
+ node_names.insert(node_id!("a"), String::from("a"));
+ node_names.insert(node_id!("b"), String::from("b"));
+ node_names.insert(node_id!("c"), String::from("c"));
+ node_names.insert(node_id!("d"), String::from("d"));
+ node_names.insert(node_id!("e"), String::from("e"));
+ node_names.insert(node_id!("f"), String::from("f"));
InfoGraph::builder()
.with_direction(GraphDir::Vertical)
.with_hierarchy(node_hierarchy)
- .with_node_infos(node_infos)
+ .with_node_names(node_names)
.with_edges(edges)
.build()
};
@@ -83,24 +83,24 @@ fn to_outcome_info_graph() -> Result<(), Box> {
node_hierarchy.insert(node_id!("e"), NodeHierarchy::new());
node_hierarchy.insert(node_id!("f"), NodeHierarchy::new());
- let mut edges = IndexMap::::new();
+ let mut edges = Edges::new();
edges.insert(edge_id!("a__c"), [node_id!("a"), node_id!("c")]);
edges.insert(edge_id!("b__e"), [node_id!("b"), node_id!("e")]);
edges.insert(edge_id!("d__e"), [node_id!("d"), node_id!("e")]);
edges.insert(edge_id!("f__e"), [node_id!("f"), node_id!("e")]);
- let mut node_infos = IndexMap::::new();
- node_infos.insert(node_id!("a"), NodeInfo::new(String::from("a")));
- node_infos.insert(node_id!("b"), NodeInfo::new(String::from("b")));
- node_infos.insert(node_id!("c"), NodeInfo::new(String::from("c")));
- node_infos.insert(node_id!("d"), NodeInfo::new(String::from("d")));
- node_infos.insert(node_id!("e"), NodeInfo::new(String::from("e")));
- node_infos.insert(node_id!("f"), NodeInfo::new(String::from("f")));
+ let mut node_names = NodeNames::new();
+ node_names.insert(node_id!("a"), String::from("a"));
+ node_names.insert(node_id!("b"), String::from("b"));
+ node_names.insert(node_id!("c"), String::from("c"));
+ node_names.insert(node_id!("d"), String::from("d"));
+ node_names.insert(node_id!("e"), String::from("e"));
+ node_names.insert(node_id!("f"), String::from("f"));
InfoGraph::builder()
.with_direction(GraphDir::Vertical)
.with_hierarchy(node_hierarchy)
- .with_node_infos(node_infos)
+ .with_node_names(node_names)
.with_edges(edges)
.build()
};
diff --git a/workspace_tests/src/items/sh_cmd_item.rs b/workspace_tests/src/items/sh_cmd_item.rs
index 20c120f65..bfede52ea 100644
--- a/workspace_tests/src/items/sh_cmd_item.rs
+++ b/workspace_tests/src/items/sh_cmd_item.rs
@@ -137,8 +137,8 @@ async fn state_clean_returns_shell_command_clean_state() -> Result<(), Box>(
@@ -186,8 +186,8 @@ async fn state_current_returns_shell_command_current_state()
graph_builder.build()
};
let flow = Flow::new(FlowId::new(crate::fn_name_short!())?, graph);
- let mut output = InMemoryTextOutput::new();
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = InMemoryTextOutput::new();
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::>(
@@ -236,8 +236,8 @@ async fn state_goal_returns_shell_command_goal_state() -> Result<(), Box>(
@@ -286,8 +286,8 @@ async fn state_diff_returns_shell_command_state_diff() -> Result<(), Box>(
@@ -331,8 +331,8 @@ async fn ensure_when_creation_required_executes_apply_exec_shell_command()
graph_builder.build()
};
let flow = Flow::new(FlowId::new(crate::fn_name_short!())?, graph);
- let mut output = InMemoryTextOutput::new();
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = InMemoryTextOutput::new();
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::>(
@@ -385,8 +385,8 @@ async fn ensure_when_exists_sync_does_not_reexecute_apply_exec_shell_command()
graph_builder.build()
};
let flow = Flow::new(FlowId::new(crate::fn_name_short!())?, graph);
- let mut output = InMemoryTextOutput::new();
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let output = InMemoryTextOutput::new();
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile!("test_profile"))
.with_flow(&flow)
.with_item_params::>(
@@ -456,8 +456,8 @@ async fn clean_when_exists_sync_executes_shell_command() -> Result<(), Box>(
diff --git a/workspace_tests/src/items/tar_x_item.rs b/workspace_tests/src/items/tar_x_item.rs
index 8a1444b70..9816e9b6e 100644
--- a/workspace_tests/src/items/tar_x_item.rs
+++ b/workspace_tests/src/items/tar_x_item.rs
@@ -47,13 +47,13 @@ async fn state_current_returns_empty_file_metadatas_when_extraction_folder_not_e
workspace,
profile,
graph,
- mut output,
+ output,
tar_path,
dest,
} = test_env(&flow_id, TAR_X2_TAR).await?;
let flow = Flow::new(flow_id, graph);
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile.clone())
.with_flow(&flow)
.with_item_params::>(
@@ -87,7 +87,7 @@ async fn state_current_returns_file_metadatas_when_extraction_folder_contains_fi
workspace,
profile,
graph,
- mut output,
+ output,
tar_path,
dest,
} = test_env(&flow_id, TAR_X2_TAR).await?;
@@ -99,7 +99,7 @@ async fn state_current_returns_file_metadatas_when_extraction_folder_contains_fi
tokio::fs::create_dir(&dest).await?;
tar::Archive::new(Cursor::new(TAR_X2_TAR)).unpack(&dest)?;
- let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(&mut output, &workspace)
+ let mut cmd_ctx = CmdCtx::builder_single_profile_single_flow(output.into(), workspace.into())
.with_profile(profile.clone())
.with_flow(&flow)
.with_item_params::>(
@@ -138,7 +138,7 @@ async fn state_goal_returns_file_metadatas_from_tar() -> Result<(), Box