use crate::package_repair_command::ToolLimits;
use crate::transaction_git::GitContext;
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::time::Duration;
const VALUE_OPTIONS: [&str; 3] = ["-b", "-B", "--reason"];
const TOOL_QUIET_WINDOW: Duration = Duration::from_secs(600);
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct RepairSwitch {
pub quiet: bool,
pub no_checkout: bool,
}
fn is_branch_letter(flag: &u8) -> bool {
return *flag == b'b' || *flag == b'B';
}
impl RepairSwitch {
pub fn from_arguments(arguments: &[OsString]) -> RepairSwitch {
let mut found: RepairSwitch = RepairSwitch::default();
let mut add_position: Option<usize> = None;
for (position, pair) in arguments.windows(2).enumerate() {
if pair[0] == "worktree" && pair[1] == "add" {
add_position = Some(position);
break;
}
}
let Some(add_at) = add_position else { return found };
let mut words = arguments[add_at + 2..].iter();
while let Some(word) = words.next() {
let bytes: &[u8] = word.as_encoded_bytes();
if bytes == b"--" {
break;
}
let mut takes_value: bool = false;
for option in VALUE_OPTIONS {
if bytes == option.as_bytes() {
takes_value = true;
break;
}
}
if takes_value {
words.next();
} else if bytes == b"--quiet" {
found.quiet = true;
} else if bytes == b"--no-checkout" {
found.no_checkout = true;
} else if bytes == b"--checkout" {
found.no_checkout = false;
} else if bytes.len() > 1 && bytes[0] == b'-' && bytes[1] != b'-' {
let flags: &[u8] = &bytes[1..];
let end: usize = match flags.iter().position(is_branch_letter) {
Some(at) => at,
None => flags.len(),
};
found.quiet |= flags[..end].contains(&b'q');
if end + 1 == flags.len() {
words.next();
}
}
}
return found;
}
}
pub fn workers_for(available: usize) -> usize {
return available.max(1);
}
#[derive(Clone, Debug)]
pub struct RepairEnvironment {
pub search_path: Option<OsString>,
pub quiet_window: Duration,
pub ceiling: Duration,
pub workers: usize,
}
impl RepairEnvironment {
pub fn from_process() -> RepairEnvironment {
let available: usize = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get);
return RepairEnvironment { search_path: std::env::var_os("PATH"), quiet_window: TOOL_QUIET_WINDOW, ceiling: crate::wait_ceilings::REPAIR_TOOL_CEILING, workers: workers_for(available) };
}
pub fn limits(&self) -> ToolLimits {
return ToolLimits { window: self.quiet_window, ceiling: self.ceiling };
}
pub fn path(&self) -> Option<&OsStr> {
return self.search_path.as_deref();
}
}
pub struct RepairRequest<'a> {
pub git: &'a GitContext,
pub source: &'a Path,
pub destination: &'a Path,
pub switch: RepairSwitch,
pub environment: &'a RepairEnvironment,
}