use crate::config_snapshot::{ConfigSnapshot, read_config_snapshot};
use crate::diagnostic_log::debug;
use crate::global_arguments::{GlobalOutcome, global_layout};
use crate::transaction_git::{GitContext, subcommand_of};
use std::ffi::{OsStr, OsString};
use std::path::Path;
pub const KEY: &str = "checkout.workers";
const PARALLEL: &str = "checkout.workers=0";
fn global_prefix_length(arguments: &[OsString]) -> usize {
let layout = global_layout(arguments);
return if layout.outcome == GlobalOutcome::Command { layout.prefix_len } else { arguments.len() };
}
pub fn typed_before_subcommand(arguments: &[OsString]) -> bool {
let before: &[OsString] = &arguments[..global_prefix_length(arguments)];
return before.iter().any(|word: &OsString| { return word.to_string_lossy().to_lowercase().contains(KEY); });
}
pub fn environment_sets<'a>(variables: impl IntoIterator<Item = (&'a OsStr, &'a OsStr)>) -> bool {
return variables.into_iter().any(|(name, value): (&OsStr, &OsStr)| {
let variable: String = name.to_string_lossy().into_owned();
return (variable.starts_with("GIT_CONFIG_KEY_") || variable == "GIT_CONFIG_PARAMETERS") && value.to_string_lossy().to_lowercase().contains(KEY);
});
}
pub fn configured(snapshot: &ConfigSnapshot) -> bool {
return snapshot.entries().iter().any(|entry| { return entry.key == KEY; });
}
pub fn parallel_checkout_wanted(context: &GitContext, cwd: &Path, arguments: &[OsString]) -> bool {
if typed_before_subcommand(arguments) {
debug("parallelCheckoutWanted", "the person typed the key; nothing is added");
return false;
}
let process: Vec<(OsString, OsString)> = std::env::vars_os().collect();
let exported = process.iter().chain(context.overlay.iter()).map(|(name, value): &(OsString, OsString)| { return (name.as_os_str(), value.as_os_str()); });
if environment_sets(exported) {
debug("parallelCheckoutWanted", "the environment sets the key; nothing is added");
return false;
}
let Some(snapshot) = read_config_snapshot(context, cwd) else {
debug("parallelCheckoutWanted", "the configuration could not be read; nothing is added");
return false;
};
let wanted: bool = !configured(&snapshot);
debug("parallelCheckoutWanted", if wanted { "no configuration file sets the key; the option is added" } else { "a configuration file sets the key; nothing is added" });
return wanted;
}
pub fn insert_parallel_checkout(arguments: &mut Vec<OsString>) {
let layout = global_layout(arguments.as_slice());
if layout.outcome != GlobalOutcome::Command {
return;
}
arguments.splice(layout.prefix_len..layout.prefix_len, [OsString::from("-c"), OsString::from(PARALLEL)]);
}
pub fn is_fallback_checkout(arguments: &[OsString]) -> bool {
return matches!(subcommand_of(arguments), Some((_index, name)) if name == "reset") && arguments.iter().any(|word: &OsString| { return word == "--hard"; });
}
#[cfg(test)]
#[path = "checkout_workers_tests.rs"]
mod tests;