diff --git a/crates/openshell-cli/src/commands/common.rs b/crates/openshell-cli/src/commands/common.rs index 7b33622f1e..75dc260ba7 100644 --- a/crates/openshell-cli/src/commands/common.rs +++ b/crates/openshell-cli/src/commands/common.rs @@ -446,7 +446,7 @@ pub fn noninteractive_active_label(step: ProvisioningStep) -> String { pub fn handle_platform_progress_event( event: &PlatformEvent, - display: &mut Option, + mut display: Option<&mut ProvisioningDisplay>, provision_start: Instant, ) -> bool { let completed_step = event @@ -472,7 +472,7 @@ pub fn handle_platform_progress_event( .metadata .get(PROGRESS_COMPLETE_LABEL_KEY) .map_or_else(|| step.completed_label(), String::as_str); - if let Some(d) = display.as_mut() { + if let Some(d) = display.as_deref_mut() { d.complete_step_with_label(step, label); } else { let ts = format_timestamp(provision_start.elapsed()); @@ -481,13 +481,13 @@ pub fn handle_platform_progress_event( } if let Some(step) = active_step - && let Some(d) = display.as_mut() + && let Some(d) = display.as_deref_mut() { d.set_active_step(step); } if let Some(detail) = active_detail { - if let Some(d) = display.as_mut() { + if let Some(d) = display { d.set_active_detail(detail); } else { let ts = format_timestamp(provision_start.elapsed()); @@ -1072,6 +1072,46 @@ mod tests { assert!(err.to_string().contains("invalid duration")); } + #[test] + fn platform_progress_events_update_borrowed_display_without_duplicate_steps() { + let event = PlatformEvent { + metadata: HashMap::from([ + ( + PROGRESS_COMPLETE_STEP_KEY.to_string(), + PROGRESS_STEP_REQUESTING_SANDBOX.to_string(), + ), + ( + PROGRESS_ACTIVE_STEP_KEY.to_string(), + PROGRESS_STEP_STARTING_SANDBOX.to_string(), + ), + ]), + ..PlatformEvent::default() + }; + let mut display = ProvisioningDisplay::new(); + + assert!(handle_platform_progress_event( + &event, + Some(&mut display), + Instant::now(), + )); + assert!(handle_platform_progress_event( + &event, + Some(&mut display), + Instant::now(), + )); + + assert_eq!( + display.completed_steps, + vec![ProvisioningStep::RequestingSandbox] + ); + assert_eq!(display.completed_bars.len(), 1); + assert_eq!( + display.active_label, + ProvisioningStep::StartingSandbox.active_label() + ); + display.clear(); + } + // helper for building input fn env(pairs: &[(&str, &str)]) -> HashMap { pairs diff --git a/crates/openshell-cli/src/run.rs b/crates/openshell-cli/src/run.rs index e376d08dc5..47fc268080 100644 --- a/crates/openshell-cli/src/run.rs +++ b/crates/openshell-cli/src/run.rs @@ -766,16 +766,10 @@ pub async fn sandbox_create( // the deadline when applicable. let handled = match &mut display { ProgressOutput::Interactive(d) => { - let mut opt = Some(std::mem::replace(d, ProvisioningDisplay::new())); - let h = handle_platform_progress_event(&ev, &mut opt, provision_start); - if let Some(inner) = opt { - *d = inner; - } - h + handle_platform_progress_event(&ev, Some(d), provision_start) } ProgressOutput::Plain => { - let mut opt: Option = None; - handle_platform_progress_event(&ev, &mut opt, provision_start) + handle_platform_progress_event(&ev, None, provision_start) } ProgressOutput::Silent => false, };