diff options
| -rw-r--r-- | .cargo/registry.toml | 3 | ||||
| -rw-r--r-- | src/cmds/status.rs | 83 | ||||
| -rw-r--r-- | src/collects.rs | 1 | ||||
| -rw-r--r-- | src/collects/status.rs | 38 | ||||
| -rw-r--r-- | src/inputs/status.rs | 44 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/systems/cmd/cmd_system.rs | 50 | ||||
| -rw-r--r-- | templates/command.rs.template | 28 |
8 files changed, 150 insertions, 98 deletions
diff --git a/.cargo/registry.toml b/.cargo/registry.toml index f581074..fd12894 100644 --- a/.cargo/registry.toml +++ b/.cargo/registry.toml @@ -40,6 +40,9 @@ path = "src/outputs.rs" [collect.inputs] path = "src/inputs.rs" +[collect.collects] +path = "src/collects.rs" + [collect.cmds] path = "src/cmds.rs" diff --git a/src/cmds/status.rs b/src/cmds/status.rs index 54e033e..cb10150 100644 --- a/src/cmds/status.rs +++ b/src/cmds/status.rs @@ -1,9 +1,12 @@ -use std::time::SystemTime; +use std::{collections::HashMap, time::SystemTime}; -use just_enough_vcs::vcs::constants::VAULT_HOST_NAME; +use just_enough_vcs::vcs::{ + constants::VAULT_HOST_NAME, data::local::workspace_analyzer::ModifiedRelativePathBuf, +}; use crate::{ arguments::status::JVStatusArgument, + collects::status::JVStatusCollect, inputs::status::JVStatusInput, outputs::status::{JVStatusOutput, JVStatusWrongModifyReason}, renderers::status::JVStatusRenderer, @@ -16,16 +19,23 @@ use crate::{ pub struct JVStatusCommand; -impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer> +impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusCollect, JVStatusOutput, JVStatusRenderer> for JVStatusCommand { async fn prepare( - _args: JVStatusArgument, - _ctx: JVCommandContext, + _args: &JVStatusArgument, + _ctx: &JVCommandContext, ) -> Result<JVStatusInput, CmdPrepareError> { + Ok(JVStatusInput) + } + + async fn collect( + _args: &JVStatusArgument, + _ctx: &JVCommandContext, + ) -> Result<JVStatusCollect, CmdPrepareError> { // Initialize a reader for the local workspace and a default result structure let mut reader = LocalWorkspaceReader::default(); - let mut input = JVStatusInput::default(); + let mut collect = JVStatusCollect::default(); // Analyze the current status of the local workspace // (detects changes like created, modified, moved, etc.) @@ -58,26 +68,31 @@ impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer let now_time = SystemTime::now(); // Populate the result structure with the gathered data - input.current_account = account; - input.current_sheet = sheet_name; - input.is_host_mode = is_host_mode; - input.in_ref_sheet = is_ref_sheet; - input.analyzed_result = analyzed; - input.update_time = update_time; - input.now_time = now_time; - input.latest_file_data = latest_file_data; - - Ok(input) + collect.current_account = account; + collect.current_sheet = sheet_name; + collect.is_host_mode = is_host_mode; + collect.in_ref_sheet = is_ref_sheet; + collect.analyzed_result = analyzed; + collect.update_time = update_time; + collect.now_time = now_time; + collect.latest_file_data = latest_file_data; + Ok(collect) } - async fn exec(mut input: JVStatusInput) -> Result<JVStatusOutput, CmdExecuteError> { - let latest_file_data = &input.latest_file_data; + async fn exec( + _input: JVStatusInput, + collect: JVStatusCollect, + ) -> Result<JVStatusOutput, CmdExecuteError> { + let mut wrong_modified_items: HashMap<ModifiedRelativePathBuf, JVStatusWrongModifyReason> = + HashMap::new(); + + let latest_file_data = &collect.latest_file_data; // Calculate whether modifications are correc - let modified = &input.analyzed_result.modified; + let modified = &collect.analyzed_result.modified; for item in modified { // Get mapping - let Ok(mapping) = input.local_sheet_data.mapping_data(&item) else { + let Ok(mapping) = collect.local_sheet_data.mapping_data(&item) else { continue; }; @@ -93,7 +108,7 @@ impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer // Base version dismatch if base_version != latest_version { - input.wrong_modified_items.insert( + wrong_modified_items.insert( item.clone(), JVStatusWrongModifyReason::BaseVersionMismatch { base_version, @@ -105,18 +120,16 @@ impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer } // Check edit right (only check when current is not HOST) - if input.current_account != VAULT_HOST_NAME { + if collect.current_account != VAULT_HOST_NAME { let holder = latest_file_data.file_holder(mapping.mapping_vfid()); if holder.is_none() { - input - .wrong_modified_items - .insert(item.clone(), JVStatusWrongModifyReason::NoHolder); + wrong_modified_items.insert(item.clone(), JVStatusWrongModifyReason::NoHolder); continue; } let holder = holder.cloned().unwrap(); - if &input.current_account != &holder { - input.wrong_modified_items.insert( + if &collect.current_account != &holder { + wrong_modified_items.insert( item.clone(), JVStatusWrongModifyReason::ModifiedButNotHeld { holder: holder }, ); @@ -125,14 +138,14 @@ impl JVCommand<JVStatusArgument, JVStatusInput, JVStatusOutput, JVStatusRenderer } let output = JVStatusOutput { - current_account: input.current_account, - current_sheet: input.current_sheet, - is_host_mode: input.is_host_mode, - in_ref_sheet: input.in_ref_sheet, - analyzed_result: input.analyzed_result, - wrong_modified_items: input.wrong_modified_items, - update_time: input.update_time, - now_time: input.now_time, + current_account: collect.current_account, + current_sheet: collect.current_sheet, + is_host_mode: collect.is_host_mode, + in_ref_sheet: collect.in_ref_sheet, + analyzed_result: collect.analyzed_result, + wrong_modified_items: wrong_modified_items, + update_time: collect.update_time, + now_time: collect.now_time, }; Ok(output) diff --git a/src/collects.rs b/src/collects.rs new file mode 100644 index 0000000..822c729 --- /dev/null +++ b/src/collects.rs @@ -0,0 +1 @@ +pub mod status; diff --git a/src/collects/status.rs b/src/collects/status.rs new file mode 100644 index 0000000..b0e8fcd --- /dev/null +++ b/src/collects/status.rs @@ -0,0 +1,38 @@ +use std::time::SystemTime; + +use just_enough_vcs::vcs::data::{ + local::{ + latest_file_data::LatestFileData, local_sheet::LocalSheetData, + workspace_analyzer::AnalyzeResultPure, + }, + member::MemberId, + sheet::SheetName, +}; + +pub struct JVStatusCollect { + pub current_account: MemberId, + pub current_sheet: SheetName, + pub is_host_mode: bool, + pub in_ref_sheet: bool, + pub analyzed_result: AnalyzeResultPure, + pub latest_file_data: LatestFileData, + pub local_sheet_data: LocalSheetData, + pub update_time: SystemTime, + pub now_time: SystemTime, +} + +impl Default for JVStatusCollect { + fn default() -> Self { + Self { + current_account: MemberId::default(), + current_sheet: SheetName::default(), + is_host_mode: false, + in_ref_sheet: false, + analyzed_result: AnalyzeResultPure::default(), + latest_file_data: LatestFileData::default(), + local_sheet_data: LocalSheetData::default(), + update_time: SystemTime::now(), + now_time: SystemTime::now(), + } + } +} diff --git a/src/inputs/status.rs b/src/inputs/status.rs index eb3b504..859ccd2 100644 --- a/src/inputs/status.rs +++ b/src/inputs/status.rs @@ -1,43 +1 @@ -use std::{collections::HashMap, time::SystemTime}; - -use just_enough_vcs::vcs::data::{ - local::{ - latest_file_data::LatestFileData, - local_sheet::LocalSheetData, - workspace_analyzer::{AnalyzeResultPure, ModifiedRelativePathBuf}, - }, - member::MemberId, - sheet::SheetName, -}; - -use crate::outputs::status::JVStatusWrongModifyReason; - -pub struct JVStatusInput { - pub current_account: MemberId, - pub current_sheet: SheetName, - pub is_host_mode: bool, - pub in_ref_sheet: bool, - pub analyzed_result: AnalyzeResultPure, - pub latest_file_data: LatestFileData, - pub local_sheet_data: LocalSheetData, - pub wrong_modified_items: HashMap<ModifiedRelativePathBuf, JVStatusWrongModifyReason>, - pub update_time: SystemTime, - pub now_time: SystemTime, -} - -impl Default for JVStatusInput { - fn default() -> Self { - Self { - current_account: MemberId::default(), - current_sheet: SheetName::default(), - is_host_mode: false, - in_ref_sheet: false, - analyzed_result: AnalyzeResultPure::default(), - latest_file_data: LatestFileData::default(), - local_sheet_data: LocalSheetData::default(), - wrong_modified_items: HashMap::new(), - update_time: SystemTime::now(), - now_time: SystemTime::now(), - } - } -} +pub struct JVStatusInput; @@ -21,6 +21,7 @@ pub mod cmds; /// Command Data pub mod arguments; +pub mod collects; pub mod inputs; pub mod outputs; diff --git a/src/systems/cmd/cmd_system.rs b/src/systems/cmd/cmd_system.rs index 65f972d..20f5aef 100644 --- a/src/systems/cmd/cmd_system.rs +++ b/src/systems/cmd/cmd_system.rs @@ -14,11 +14,12 @@ pub struct JVCommandContext { pub confirmed: bool, } -pub trait JVCommand<Argument, Input, Output, Renderer> +pub trait JVCommand<Argument, Input, Collect, Output, Renderer> where - Argument: clap::Parser + Send + Sync, - Input: Send + Sync, + Argument: clap::Parser + Send, + Input: Send, Output: Serialize + Send + Sync, + Collect: Send, Renderer: JVResultRenderer<Output> + Send + Sync, { /// Get help string for the command @@ -52,7 +53,7 @@ where /// Process the command output with a custom renderer, /// performing any necessary post-execution processing - fn process_with_renderer<R: JVResultRenderer<Output> + Send + Sync>( + fn process_with_renderer<R: JVResultRenderer<Output> + Send>( args: Vec<String>, ctx: JVCommandContext, ) -> impl Future<Output = Result<JVRenderResult, CmdProcessError>> + Send @@ -61,40 +62,59 @@ where { async move { let mut full_args = vec!["jv".to_string()]; + full_args.extend(args); + let parsed_args = match Argument::try_parse_from(full_args) { Ok(args) => args, Err(_) => return Err(CmdProcessError::ParseError(Self::get_help_str())), }; + // If the help flag is used, skip execution and directly print help if ctx.help { let mut r = JVRenderResult::default(); r_println!(r, "{}", Self::get_help_str()); return Ok(r); } - let input = match Self::prepare(parsed_args, ctx).await { - Ok(input) => input, + + let (input, collect) = match tokio::try_join!( + Self::prepare(&parsed_args, &ctx), + Self::collect(&parsed_args, &ctx) + ) { + Ok((input, collect)) => (input, collect), Err(e) => return Err(CmdProcessError::from(e)), }; - let output = match Self::exec(input).await { + + let output = match Self::exec(input, collect).await { Ok(output) => output, Err(e) => return Err(CmdProcessError::from(e)), }; + match R::render(&output).await { Ok(r) => Ok(r), Err(e) => Err(CmdProcessError::from(e)), } } } - - /// Prepare to run the command, - /// converting Clap input into the command's supported input + /// Prepare + /// Converts Argument input into parameters readable during the execution phase fn prepare( - args: Argument, - ctx: JVCommandContext, + args: &Argument, + ctx: &JVCommandContext, ) -> impl Future<Output = Result<Input, CmdPrepareError>> + Send; - /// Run the command phase, - /// returning an output structure, waiting for rendering - fn exec(input: Input) -> impl Future<Output = Result<Output, CmdExecuteError>> + Send; + /// Resource collection + /// Reads required resources and sends them to the `exec` function + fn collect( + args: &Argument, + ctx: &JVCommandContext, + ) -> impl Future<Output = Result<Collect, CmdPrepareError>> + Send; + + /// Execute + /// Executes the results obtained from `prepare` and `collect` + /// Returns data that can be used for rendering + fn exec( + input: Input, + collect: Collect, + ) -> impl Future<Output = Result<Output, CmdExecuteError>> + Send; } diff --git a/templates/command.rs.template b/templates/command.rs.template index 1c56c29..98d495d 100644 --- a/templates/command.rs.template +++ b/templates/command.rs.template @@ -14,20 +14,38 @@ pub struct JVUnknownArgument; pub struct JVUnknownInput; +pub struct JVUnknownCollect; + #[derive(Serialize)] pub struct JVUnknownOutput; -impl JVCommand<JVUnknownArgument, JVUnknownInput, JVUnknownOutput, JVStatusRenderer> - for JVUnknownCommand +impl + JVCommand< + JVUnknownArgument, // Argument + JVUnknownInput, // Input Data + JVUnknownCollect, // Collect Resources + JVUnknownOutput, // Output Data + JVStatusRenderer, // Default Renderer + > for JVUnknownCommand { async fn prepare( - _args: JVUnknownArgument, - _ctx: JVCommandContext, + _args: &JVUnknownArgument, + _ctx: &JVCommandContext, ) -> Result<JVUnknownInput, CmdPrepareError> { todo!() } - async fn exec(_input: JVUnknownInput) -> Result<JVUnknownOutput, CmdExecuteError> { + async fn collect( + _args: &JVUnknownArgument, + _ctx: &JVCommandContext, + ) -> Result<JVUnknownCollect, CmdPrepareError> { + todo!() + } + + async fn exec( + _input: JVUnknownInput, + _collect: JVUnknownCollect, + ) -> Result<JVUnknownOutput, CmdExecuteError> { todo!() } |
