use crate::core::Process;
#[cfg(unix)]
use crate::core::{apply_filters, apply_to_each, NameMatch};
use crate::error::Result;
#[cfg(unix)]
use crate::ui::{must_confirm, plural, prompt, Printer};
use clap::Args;
#[derive(Args, Debug)]
pub struct OrphansCommand {
#[arg(long, short = 'k')]
pub kill: bool,
#[arg(long)]
pub dry_run: bool,
#[arg(long, short = 'y')]
pub yes: bool,
#[arg(long, short = 'j')]
pub json: bool,
#[arg(long, short = 'v')]
pub verbose: bool,
#[arg(long, short = 'w')]
pub wide: bool,
#[arg(long = "in", short = 'i', num_args = 0..=1, default_missing_value = ".")]
pub in_dir: Option<String>,
#[arg(long = "by", short = 'b')]
pub by_name: Option<String>,
#[arg(long)]
pub cmd: bool,
}
impl OrphansCommand {
#[cfg(unix)]
pub fn execute(&self) -> Result<()> {
let printer = Printer::from_flags(self.json, self.verbose).wide(self.wide);
let mut processes = Process::find_orphans()?;
apply_filters(
&mut processes,
&self.in_dir,
&self.by_name,
NameMatch::from_flag(self.cmd),
)?;
if !(self.kill && self.json && self.yes && !self.dry_run) {
Process::measure_cpu(&mut processes);
}
if processes.is_empty() {
printer.print_empty_result("orphans", "No orphaned processes found");
return Ok(());
}
printer.warning(&format!(
"Found {} orphaned process{}",
processes.len(),
plural(processes.len())
));
if !self.kill {
printer.print_processes_under_headline("orphans", &processes);
return Ok(());
}
if self.dry_run {
printer.print_dry_run_with(
"orphans",
&processes,
&format!(
"Dry run: would kill {} orphaned process{}",
processes.len(),
plural(processes.len())
),
);
return Ok(());
}
let asking = must_confirm("orphans --kill", self.yes, self.json, &processes, None);
if !self.json && !matches!(asking, Ok(true)) {
printer.print_processes_under_headline("orphans", &processes);
}
if asking? {
let question = format!(
"Kill {} orphaned process{}?",
processes.len(),
plural(processes.len())
);
let list = || printer.print_processes_under_headline("orphans", &processes);
let confirmed = prompt::ask("orphans --kill", &processes, None, &question, list)?;
if !confirmed {
printer.warning("Cancelled");
return Ok(());
}
}
let (killed, failed) = apply_to_each(&processes, |proc| proc.kill_and_wait());
printer.print_action_result_as("orphans", "kill", &killed, &failed)
}
#[cfg(not(unix))]
pub fn execute(&self) -> Result<()> {
Process::find_orphans().map(|_| ())
}
}