feat: implement --noconfirm
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use clap::{Arg, ArgMatches, Command};
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||
use path_absolutize::Absolutize;
|
||||
|
||||
use crate::action::*;
|
||||
@@ -100,16 +100,22 @@ fn get_group_cmd() -> Command {
|
||||
fn get_package_cmd() -> Command {
|
||||
let sync = Command::new(SYNC)
|
||||
.about("install packages from all imported groups")
|
||||
.visible_alias("sy");
|
||||
.visible_alias("sy")
|
||||
.arg(build_noconfirm_arg());
|
||||
|
||||
let clean = Command::new(CLEAN)
|
||||
.about("remove unmanaged packages")
|
||||
.visible_alias("c");
|
||||
.visible_alias("c")
|
||||
.arg(build_noconfirm_arg());
|
||||
|
||||
let unmanaged = Command::new(UNMANAGED)
|
||||
.about("show explicitly installed packages not managed by pacdef")
|
||||
.visible_alias("u");
|
||||
|
||||
let review = Command::new(REVIEW)
|
||||
.about("review unmanaged packages")
|
||||
.visible_alias("r");
|
||||
|
||||
let search = Command::new(SEARCH)
|
||||
.visible_alias("se")
|
||||
.about("search for packages which match a provided regex")
|
||||
@@ -128,6 +134,13 @@ fn get_package_cmd() -> Command {
|
||||
.subcommands([clean, review, unmanaged, search, sync])
|
||||
}
|
||||
|
||||
fn build_noconfirm_arg() -> Arg {
|
||||
Arg::new("noconfirm")
|
||||
.long("noconfirm")
|
||||
.help("do not ask for any confirmation")
|
||||
.action(ArgAction::SetTrue)
|
||||
}
|
||||
|
||||
/// Get and parse the CLI arguments.
|
||||
#[must_use]
|
||||
pub fn get() -> clap::ArgMatches {
|
||||
|
||||
@@ -21,6 +21,7 @@ const SECTION: Text = "arch";
|
||||
const SWITCHES_INFO: Switches = &["--query", "--info"];
|
||||
const SWITCHES_INSTALL: Switches = &["--sync"];
|
||||
const SWITCHES_MAKE_DEPENDENCY: Switches = &["--database", "--asdeps"];
|
||||
const SWITCHES_NOCONFIRM: Switches = &["--noconfirm"];
|
||||
const SWITCHES_REMOVE: Switches = &["--remove", "--recursive"];
|
||||
|
||||
const SUPPORTS_AS_DEPENDENCY: bool = true;
|
||||
@@ -49,11 +50,15 @@ impl Backend for Arch {
|
||||
}
|
||||
|
||||
/// Install the specified packages.
|
||||
fn install_packages(&self, packages: &[Package]) -> Result<ExitStatus> {
|
||||
fn install_packages(&self, packages: &[Package], noconfirm: bool) -> Result<ExitStatus> {
|
||||
let mut cmd = Command::new(&self.binary);
|
||||
|
||||
cmd.args(self.get_switches_install());
|
||||
|
||||
if noconfirm {
|
||||
cmd.args(self.get_switches_noconfirm());
|
||||
}
|
||||
|
||||
for p in packages {
|
||||
cmd.arg(format!("{p}"));
|
||||
}
|
||||
@@ -63,7 +68,7 @@ impl Backend for Arch {
|
||||
}
|
||||
|
||||
/// Remove the specified packages.
|
||||
fn remove_packages(&self, packages: &[Package]) -> Result<ExitStatus> {
|
||||
fn remove_packages(&self, packages: &[Package], noconfirm: bool) -> Result<ExitStatus> {
|
||||
let mut cmd = Command::new(&self.binary);
|
||||
|
||||
cmd.args(self.get_switches_remove());
|
||||
@@ -71,6 +76,10 @@ impl Backend for Arch {
|
||||
cmd.args(rm_args);
|
||||
}
|
||||
|
||||
if noconfirm {
|
||||
cmd.args(self.get_switches_noconfirm());
|
||||
}
|
||||
|
||||
for p in packages {
|
||||
cmd.arg(format!("{p}"));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ const SECTION: Text = "debian";
|
||||
const SWITCHES_INFO: Switches = &["show"];
|
||||
const SWITCHES_INSTALL: Switches = &["install"];
|
||||
const SWITCHES_MAKE_DEPENDENCY: Switches = &[]; // not needed
|
||||
const SWITCHES_NOCONFIRM: Switches = &["--yes"];
|
||||
const SWITCHES_REMOVE: Switches = &["remove"];
|
||||
|
||||
const SUPPORTS_AS_DEPENDENCY: bool = true;
|
||||
|
||||
@@ -20,6 +20,7 @@ const SECTION: Text = "python";
|
||||
const SWITCHES_INFO: Switches = &["show"];
|
||||
const SWITCHES_INSTALL: Switches = &["install"];
|
||||
const SWITCHES_MAKE_DEPENDENCY: Switches = &[]; // not needed
|
||||
const SWITCHES_NOCONFIRM: Switches = &[]; // not needed
|
||||
const SWITCHES_REMOVE: Switches = &["uninstall"];
|
||||
|
||||
const SUPPORTS_AS_DEPENDENCY: bool = false;
|
||||
|
||||
@@ -20,6 +20,7 @@ const SECTION: Text = "rust";
|
||||
const SWITCHES_INSTALL: Switches = &["install"];
|
||||
const SWITCHES_INFO: Switches = &["search", "--limit", "1"];
|
||||
const SWITCHES_MAKE_DEPENDENCY: Switches = &[];
|
||||
const SWITCHES_NOCONFIRM: Switches = &[]; // not needed
|
||||
const SWITCHES_REMOVE: Switches = &["uninstall"];
|
||||
|
||||
const SUPPORTS_AS_DEPENDENCY: bool = false;
|
||||
|
||||
@@ -37,6 +37,10 @@ pub trait Backend: Debug {
|
||||
/// Get CLI switches for the package manager to install packages.
|
||||
fn get_switches_install(&self) -> Switches;
|
||||
|
||||
/// Get CLI switches for the package manager to perform `sync` and `clean` without
|
||||
/// confirmation.
|
||||
fn get_switches_noconfirm(&self) -> Switches;
|
||||
|
||||
/// Get CLI switches for the package manager to remove packages.
|
||||
fn get_switches_remove(&self) -> Switches;
|
||||
|
||||
@@ -73,12 +77,18 @@ pub trait Backend: Debug {
|
||||
}
|
||||
|
||||
/// Install the specified packages.
|
||||
fn install_packages(&self, packages: &[Package]) -> Result<ExitStatus> {
|
||||
fn install_packages(&self, packages: &[Package], noconfirm: bool) -> Result<ExitStatus> {
|
||||
let mut cmd = Command::new(self.get_binary());
|
||||
cmd.args(self.get_switches_install());
|
||||
|
||||
if noconfirm {
|
||||
cmd.args(self.get_switches_noconfirm());
|
||||
}
|
||||
|
||||
for p in packages {
|
||||
cmd.arg(format!("{p}"));
|
||||
}
|
||||
|
||||
cmd.status()
|
||||
.with_context(|| format!("running command {cmd:?}"))
|
||||
}
|
||||
@@ -92,20 +102,28 @@ pub trait Backend: Debug {
|
||||
fn make_dependency(&self, packages: &[Package]) -> Result<ExitStatus> {
|
||||
let mut cmd = Command::new(self.get_binary());
|
||||
cmd.args(self.get_switches_make_dependency());
|
||||
|
||||
for p in packages {
|
||||
cmd.arg(format!("{p}"));
|
||||
}
|
||||
|
||||
cmd.status()
|
||||
.with_context(|| format!("running command [{cmd:?}]"))
|
||||
}
|
||||
|
||||
/// Remove the specified packages.
|
||||
fn remove_packages(&self, packages: &[Package]) -> Result<ExitStatus> {
|
||||
fn remove_packages(&self, packages: &[Package], noconfirm: bool) -> Result<ExitStatus> {
|
||||
let mut cmd = Command::new(self.get_binary());
|
||||
cmd.args(self.get_switches_remove());
|
||||
|
||||
if noconfirm {
|
||||
cmd.args(self.get_switches_noconfirm());
|
||||
}
|
||||
|
||||
for p in packages {
|
||||
cmd.arg(format!("{p}"));
|
||||
}
|
||||
|
||||
cmd.status()
|
||||
.with_context(|| format!("running command [{cmd:?}]"))
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@ macro_rules! impl_backend_constants {
|
||||
SWITCHES_INSTALL
|
||||
}
|
||||
|
||||
fn get_switches_noconfirm(&self) -> Switches {
|
||||
SWITCHES_NOCONFIRM
|
||||
}
|
||||
|
||||
fn get_switches_remove(&self) -> Switches {
|
||||
SWITCHES_REMOVE
|
||||
}
|
||||
|
||||
@@ -35,31 +35,37 @@ impl ToDoPerBackend {
|
||||
self.0.iter().all(|(_, diff)| diff.is_empty())
|
||||
}
|
||||
|
||||
pub(crate) fn install_missing_packages(&self) -> Result<()> {
|
||||
self.handle_backend_command(Backend::install_packages, "install", "installing")
|
||||
.context("installing packages")
|
||||
pub(crate) fn install_missing_packages(&self, noconfirm: bool) -> Result<()> {
|
||||
self.handle_backend_command(
|
||||
Backend::install_packages,
|
||||
noconfirm,
|
||||
"install",
|
||||
"installing",
|
||||
)
|
||||
.context("installing packages")
|
||||
}
|
||||
|
||||
pub(crate) fn remove_unmanaged_packages(&self) -> Result<()> {
|
||||
self.handle_backend_command(Backend::remove_packages, "remove", "removing")
|
||||
pub(crate) fn remove_unmanaged_packages(&self, noconfirm: bool) -> Result<()> {
|
||||
self.handle_backend_command(Backend::remove_packages, noconfirm, "remove", "removing")
|
||||
.context("removing packages")
|
||||
}
|
||||
|
||||
fn handle_backend_command<'a, F>(
|
||||
&'a self,
|
||||
func: F,
|
||||
noconfirm: bool,
|
||||
verb: &'_ str,
|
||||
verb_continuous: &'_ str,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: Fn(&'a dyn Backend, &'a [Package]) -> Result<ExitStatus>,
|
||||
F: Fn(&'a dyn Backend, &'a [Package], bool) -> Result<ExitStatus>,
|
||||
{
|
||||
for (backend, packages) in &self.0 {
|
||||
if packages.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let exit_status = func(&**backend, packages).with_context(|| {
|
||||
let exit_status = func(&**backend, packages, noconfirm).with_context(|| {
|
||||
format!("{verb_continuous} packages for {}", backend.get_section())
|
||||
})?;
|
||||
|
||||
|
||||
@@ -71,13 +71,13 @@ impl Pacdef {
|
||||
},
|
||||
|
||||
Some(("package", args)) => match args.subcommand() {
|
||||
Some((CLEAN, _)) => self.clean_packages(),
|
||||
Some((CLEAN, args)) => self.clean_packages(&args.clone()),
|
||||
Some((REVIEW, _)) => review::review(self.get_unmanaged_packages()?, self.groups)
|
||||
.context("review unmanaged packages"),
|
||||
Some((SEARCH, args)) => {
|
||||
search::search_packages(args, &self.groups).context("searching packages")
|
||||
}
|
||||
Some((SYNC, _)) => self.install_packages(),
|
||||
Some((SYNC, args)) => self.install_packages(&args.clone()), // TODO fix cloning
|
||||
Some((UNMANAGED, _)) => self.show_unmanaged_packages(),
|
||||
|
||||
Some((_, _)) => panic!("{ACTION_NOT_MATCHED}"),
|
||||
@@ -130,7 +130,7 @@ impl Pacdef {
|
||||
}
|
||||
}
|
||||
|
||||
fn install_packages(&mut self) -> Result<()> {
|
||||
fn install_packages(&mut self, args: &ArgMatches) -> Result<()> {
|
||||
let to_install = self.get_missing_packages()?;
|
||||
|
||||
if to_install.nothing_to_do_for_all_backends() {
|
||||
@@ -141,12 +141,18 @@ impl Pacdef {
|
||||
println!("Would install the following packages:\n");
|
||||
to_install.show().context("printing things to do")?;
|
||||
|
||||
println!();
|
||||
if !get_user_confirmation()? {
|
||||
return Ok(());
|
||||
};
|
||||
let noconfirm = *args
|
||||
.get_one::<bool>("noconfirm")
|
||||
.expect("has a default value");
|
||||
|
||||
to_install.install_missing_packages()
|
||||
println!();
|
||||
if noconfirm {
|
||||
println!("proceeding without confirmation");
|
||||
} else if !get_user_confirmation()? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
to_install.install_missing_packages(noconfirm)
|
||||
}
|
||||
|
||||
fn edit_group_files(&self, arg_matches: &ArgMatches) -> Result<()> {
|
||||
@@ -220,7 +226,7 @@ impl Pacdef {
|
||||
}
|
||||
}
|
||||
|
||||
fn clean_packages(mut self) -> Result<()> {
|
||||
fn clean_packages(&mut self, args: &ArgMatches) -> Result<()> {
|
||||
let to_remove = self.get_unmanaged_packages()?;
|
||||
|
||||
if to_remove.nothing_to_do_for_all_backends() {
|
||||
@@ -231,12 +237,18 @@ impl Pacdef {
|
||||
println!("Would remove the following packages:\n");
|
||||
to_remove.show().context("printing things to do")?;
|
||||
|
||||
println!();
|
||||
if !get_user_confirmation()? {
|
||||
return Ok(());
|
||||
};
|
||||
let noconfirm = *args
|
||||
.get_one::<bool>("noconfirm")
|
||||
.expect("has a default value");
|
||||
|
||||
to_remove.remove_unmanaged_packages()
|
||||
println!();
|
||||
if noconfirm {
|
||||
println!("proceeding without confirmation");
|
||||
} else if !get_user_confirmation()? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
to_remove.remove_unmanaged_packages(noconfirm)
|
||||
}
|
||||
|
||||
fn show_group_content(&self, groups: &ArgMatches) -> Result<()> {
|
||||
|
||||
@@ -30,7 +30,7 @@ impl Strategy {
|
||||
|
||||
pub(super) fn execute(self) -> Result<()> {
|
||||
if !self.delete.is_empty() {
|
||||
ensure!(self.backend.remove_packages(&self.delete)?.success());
|
||||
ensure!(self.backend.remove_packages(&self.delete, false)?.success());
|
||||
}
|
||||
|
||||
if !self.as_dependency.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user