use crate::config::gate_args::GateArgs;
use crate::config::test_path_scanner::TestPathScanner;
use std::fs::read_to_string;
pub struct JobSource;
impl JobSource {
pub fn apply(args: GateArgs) -> Result<GateArgs, String> {
let jobs = Self::resolve(&args)?;
Ok(GateArgs { jobs, ..args })
}
pub fn resolve(args: &GateArgs) -> Result<Vec<String>, String> {
let stated: Vec<&str> = [
(!args.jobs.is_empty()).then_some("--jobs"),
(!args.jobs_paths.is_empty()).then_some("--jobs-path"),
args.jobs_file.is_some().then_some("--jobs-file"),
]
.into_iter()
.flatten()
.collect();
match stated.as_slice() {
["--jobs"] => Ok(args.jobs.clone()),
["--jobs-path"] => TestPathScanner::scan(&args.jobs_paths),
["--jobs-file"] => Self::read(&Self::file_path_of(args)),
[] => Err("no jobs to run; pass --jobs, --jobs-path or --jobs-file".to_string()),
several => Err(format!(
"{} were all given; state the job list once",
several.join(" and ")
)),
}
}
fn file_path_of(args: &GateArgs) -> String {
args.jobs_file
.as_ref()
.map(|path| path.to_string_lossy().into_owned())
.unwrap_or_default()
}
fn read(path: &str) -> Result<Vec<String>, String> {
let contents = read_to_string(path)
.map_err(|error| format!("--jobs-file {path} could not be read: {error}"))?;
let names: Vec<String> = contents
.strip_prefix('\u{feff}')
.unwrap_or(&contents)
.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.map(str::to_string)
.collect();
if names.is_empty() {
return Err(format!("--jobs-file {path} names no jobs"));
}
Ok(names)
}
}