- Split monolithic src/lib.rs (~640 lines) into 7 sub-modules: types.rs, context.rs, user_data.rs, translate.rs, http.rs, csv_util.rs, test_utils.rs - Add configurable --output-dir CLI option for CSV output files - Implement atomic file writes (write-to-temp + rename) for all CSVs - Change compute_car_counts() to return CarCounts directly (not Result) - Add test-utils feature gate for shared test helpers - Add HTTP mock tests with mockito (6 tests) - Add proptest tests for compute_car_counts (3 property tests) - Update integration tests to use shared test utilities - Update documentation (API.md, ARCHITECTURE.md, DATA_STRUCTURES.md)
63 lines
2.2 KiB
Rust
63 lines
2.2 KiB
Rust
//! Command dispatch and shared helpers.
|
|
//!
|
|
//! Provides the `run_analysis` orchestration function and `load_my_cars_or_warn`
|
|
//! helper used by all command handlers.
|
|
|
|
pub mod all;
|
|
pub mod best;
|
|
pub mod details;
|
|
pub mod fetch;
|
|
pub mod track;
|
|
pub mod trash;
|
|
pub mod wishlist;
|
|
|
|
use std::collections::HashSet;
|
|
use std::sync::Arc;
|
|
|
|
use top_drives::{
|
|
AppError, AnalysisContext, CarCounts, MyCarsData,
|
|
compute_car_counts, load_my_cars_data,
|
|
};
|
|
|
|
use crate::parsing::parse_all_times;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helper: load my_cars.json with graceful degradation
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Loads user car data, printing a warning and returning empty data if the file is missing.
|
|
///
|
|
/// Only `MissingFile` errors are gracefully degraded — parse errors and other
|
|
/// failures are propagated to the caller, because running analysis with
|
|
/// silently-corrupted ownership data would produce misleading results.
|
|
pub fn load_my_cars_or_warn(path: &str) -> Result<MyCarsData, AppError> {
|
|
match load_my_cars_data(path) {
|
|
Ok(data) => Ok(data),
|
|
Err(AppError::MissingFile(msg)) => {
|
|
eprintln!("Warning: {msg}");
|
|
eprintln!(" Analysis will run without ownership data.");
|
|
Ok(MyCarsData::default())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Analysis orchestration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Common analysis setup: loads user data, parses all timing files, and computes car counts.
|
|
///
|
|
/// Returns the analysis context (for stdout commands) and the aggregated car counts
|
|
/// (for CSV output commands). The car list is stored inside `CarCounts`.
|
|
pub async fn run_analysis(
|
|
owned: &HashSet<String>,
|
|
cars_db_path: &str,
|
|
times_dir: &str,
|
|
) -> Result<(AnalysisContext, CarCounts), AppError> {
|
|
let ctx = AnalysisContext::new();
|
|
let owned = Arc::new(owned.clone());
|
|
let car_list = parse_all_times(owned, &ctx, cars_db_path, times_dir).await?;
|
|
let counts = compute_car_counts(&ctx, car_list);
|
|
Ok((ctx, counts))
|
|
}
|