diff --git a/CHANGELOG.md b/CHANGELOG.md index 80e000a1..01a2fb24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ + + +## 6.1.1 (UNRELEASED) + +- Run the final check of all exercises in parallel. +- Small exercise improvements. + ## 6.1.0 (2024-07-10) diff --git a/src/app_state.rs b/src/app_state.rs index 8995e81c..40c91308 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -1,11 +1,11 @@ -use anyhow::{bail, Context, Result}; -use ratatui::crossterm::style::Stylize; +use anyhow::{bail, Context, Error, Result}; use serde::Deserialize; use std::{ fs::{self, File}, io::{Read, StdoutLock, Write}, path::{Path, PathBuf}, process::{Command, Stdio}, + thread, }; use crate::{ @@ -373,34 +373,50 @@ impl AppState { if let Some(ind) = self.next_pending_exercise_ind() { self.set_current_exercise_ind(ind)?; - return Ok(ExercisesProgress::NewPending); } writer.write_all(RERUNNING_ALL_EXERCISES_MSG)?; - let mut output = Vec::with_capacity(OUTPUT_CAPACITY); - for (exercise_ind, exercise) in self.exercises().iter().enumerate() { - write!(writer, "Running {exercise} ... ")?; - writer.flush()?; + let n_exercises = self.exercises.len(); - let success = exercise.run_exercise(&mut output, &self.target_dir)?; - if !success { - writeln!(writer, "{}\n", "FAILED".red())?; + let pending_exercise_ind = thread::scope(|s| { + let handles = self + .exercises + .iter_mut() + .map(|exercise| { + s.spawn(|| { + let mut output = Vec::with_capacity(OUTPUT_CAPACITY); + let success = exercise.run_exercise(&mut output, &self.target_dir)?; + exercise.done = success; + Ok::<_, Error>(success) + }) + }) + .collect::>(); - self.current_exercise_ind = exercise_ind; + for (exercise_ind, handle) in handles.into_iter().enumerate() { + write!(writer, "\rProgress: {exercise_ind}/{n_exercises}")?; + writer.flush()?; - // No check if the exercise is done before setting it to pending - // because no pending exercise was found. - self.exercises[exercise_ind].done = false; - self.n_done -= 1; - - self.write()?; - - return Ok(ExercisesProgress::NewPending); + let success = handle.join().unwrap()?; + if !success { + writer.write_all(b"\n\n")?; + return Ok(Some(exercise_ind)); + } } - writeln!(writer, "{}", "ok".green())?; + Ok::<_, Error>(None) + })?; + + if let Some(pending_exercise_ind) = pending_exercise_ind { + self.current_exercise_ind = pending_exercise_ind; + self.n_done = self + .exercises + .iter() + .filter(|exercise| exercise.done) + .count() as u16; + self.write()?; + return Ok(ExercisesProgress::NewPending); } // Write that the last exercise is done. @@ -426,7 +442,6 @@ Try running `cargo --version` to diagnose the problem."; const RERUNNING_ALL_EXERCISES_MSG: &[u8] = b" All exercises seem to be done. Recompiling and running all exercises to make sure that all of them are actually done. - "; const FENISH_LINE: &str = "+----------------------------------------------------+