use crate::side_by_side_threads::run_beside_caller;
use crate::add_timing::{begin_work, end_work};
use crate::diagnostic_log::debug;
use crate::package_repair_cargo::repair_cargo;
use crate::package_repair_pnpm::repair_pnpm;
pub use crate::package_repair_request::{RepairEnvironment, RepairRequest, RepairSwitch, workers_for};
use crate::package_repair_report::{Finding, render};
use crate::package_repair_toolchain::repair_toolchain;
use std::io::Write;
const TAG: &str = "packageRepair";
fn settled(joined: std::thread::Result<Option<Finding>>, tool: &str) -> Option<Finding> {
return match joined {
Ok(finding) => finding,
Err(_panic) => {
debug(TAG, format!("the {tool} repair stopped unexpectedly and reports nothing").as_str());
None
}
};
}
fn repair_side_by_side(request: &RepairRequest<'_>) -> (Option<Finding>, Vec<Finding>, Option<Finding>) {
let (pnpm, (toolchain, cargo)): (std::thread::Result<Option<Finding>>, ToolchainAndCargo) =
run_beside_caller((request, repair_pnpm_timed), (request, repair_toolchain_beside_cargo));
return (settled(pnpm, "pnpm"), cargo, settled(toolchain, "toolchain"));
}
type ToolchainAndCargo = (std::thread::Result<Option<Finding>>, Vec<Finding>);
fn repair_pnpm_timed(request: &RepairRequest<'_>) -> Option<Finding> {
let began: std::time::Instant = begin_work();
let found: Option<Finding> = repair_pnpm(request.destination, request.environment);
end_work("repairPnpm", began);
return found;
}
fn repair_toolchain_timed(request: &RepairRequest<'_>) -> Option<Finding> {
let began: std::time::Instant = begin_work();
let found: Option<Finding> = repair_toolchain(request.destination, request.environment);
end_work("repairToolchain", began);
return found;
}
fn repair_cargo_timed(request: &RepairRequest<'_>) -> Vec<Finding> {
let began: std::time::Instant = begin_work();
let cargo: Vec<Finding> = repair_cargo(request);
end_work("repairCargo", began);
return cargo;
}
fn repair_toolchain_beside_cargo(request: &RepairRequest<'_>) -> ToolchainAndCargo {
return run_beside_caller((request, repair_toolchain_timed), (request, repair_cargo_timed));
}
pub fn repair_worktree(request: &RepairRequest<'_>, notices: &mut dyn Write) -> Vec<Finding> {
if request.switch.no_checkout {
debug(TAG, format!("{}: --no-checkout, so there is nothing to repair", request.destination.display()).as_str());
return Vec::new();
}
let started: std::time::Instant = std::time::Instant::now();
let (pnpm, cargo, toolchain): (Option<Finding>, Vec<Finding>, Option<Finding>) = repair_side_by_side(request);
let findings: Vec<Finding> = pnpm.into_iter().chain(cargo).chain(toolchain).collect();
debug(TAG, format!("{}: {} findings in {} ms", request.destination.display(), findings.len(), started.elapsed().as_millis()).as_str());
let text: String = render(request.destination, findings.as_slice(), request.switch.quiet);
let _written = notices.write_all(text.as_bytes());
return findings;
}
#[cfg(test)]
#[path = "package_repair_tests.rs"]
mod tests;