From b8507025f6c69c8e3917039d52dd101536a5bd8f Mon Sep 17 00:00:00 2001 From: Trivernis Date: Sun, 17 Apr 2022 20:41:59 +0200 Subject: [PATCH] Wrap commands with ShellCommand builder Signed-off-by: Trivernis --- Cargo.toml | 1 - src/database/add.rs | 3 +- src/database/initialise.rs | 8 +- src/internal/commands.rs | 186 +++++++++++++++++++--------------- src/{ => internal}/error.rs | 9 +- src/internal/exit_code.rs | 12 +++ src/internal/initialise.rs | 9 +- src/internal/mod.rs | 9 +- src/internal/strings.rs | 15 +-- src/main.rs | 46 ++++++--- src/operations/aur_install.rs | 43 +++++--- src/operations/install.rs | 33 ++++-- src/operations/search.rs | 34 ++++--- src/operations/uninstall.rs | 11 +- src/operations/upgrade.rs | 11 +- 15 files changed, 274 insertions(+), 156 deletions(-) rename src/{ => internal}/error.rs (74%) create mode 100644 src/internal/exit_code.rs diff --git a/Cargo.toml b/Cargo.toml index 0ef869c..2142ee1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,6 @@ codegen-units = 1 mimalloc = { version = "0.1.27", default-features = false } clap = { version = "3.1.9", features = [ "derive", "wrap_help"] } regex = { version = "1.5.4", default-features = false, features = ["std", "unicode-perl"] } -runas = "0.2.1" rusqlite = { version = "0.26.3", default-features = false } ureq = { version = "2.4.0", default-features = false, features = ["native-tls", "json"] } serde = { version = "1.0.90", default-features = false, features = ["derive", "serde_derive"] } diff --git a/src/database/add.rs b/src/database/add.rs index e96324f..07cbd9a 100644 --- a/src/database/add.rs +++ b/src/database/add.rs @@ -3,6 +3,7 @@ use std::path::Path; use rusqlite::Connection; +use crate::internal::exit_code::AppExitCode; use crate::internal::rpc::Package; use crate::{crash, log, Options}; @@ -20,6 +21,6 @@ pub fn add(pkg: Package, options: Options) { conn.execute("INSERT OR REPLACE INTO packages (name, version, description, depends, make_depends) VALUES (?1, ?2, ?3, ?4, ?5)", [&pkg.name, &pkg.version, &pkg.description.unwrap_or_else(|| "No description found.".parse().unwrap()), &pkg.depends.join(" "), &pkg.make_depends.join(" ")], ).unwrap_or_else(|e| - crash(format!("Failed adding package {} to the database: {}", pkg.name, e), 2) + crash(format!("Failed adding package {} to the database: {}", pkg.name, e), AppExitCode::FailedAddingPkg) ); } diff --git a/src/database/initialise.rs b/src/database/initialise.rs index a5cef65..89105d7 100644 --- a/src/database/initialise.rs +++ b/src/database/initialise.rs @@ -3,6 +3,7 @@ use std::path::Path; use rusqlite::Connection; +use crate::internal::exit_code::AppExitCode; use crate::{crash, log, Options}; pub fn init(options: Options) { @@ -31,5 +32,10 @@ pub fn init(options: Options) { )", [], ) - .unwrap_or_else(|e| crash(format!("Couldn't initialise database: {}", e), 3)); + .unwrap_or_else(|e| { + crash( + format!("Couldn't initialise database: {}", e), + AppExitCode::FailedInitDb, + ) + }); } diff --git a/src/internal/commands.rs b/src/internal/commands.rs index 91a5dbd..d9270a2 100644 --- a/src/internal/commands.rs +++ b/src/internal/commands.rs @@ -1,105 +1,125 @@ -use crate::error::{AppError, AppResult}; -use crate::internal::uwu_enabled; -use crate::uwu; +use crate::internal::error::{AppError, AppResult}; use std::ffi::{OsStr, OsString}; -use std::io::{BufRead, BufReader}; -use std::process::{ChildStderr, ChildStdout, Command, Stdio}; +use std::process::{Child, Command, ExitStatus, Stdio}; -/// Executes a makepkg command -#[inline] -pub fn makepkg, S: AsRef>(args: I) -> AppResult { - run_command("makepkg", args) +pub struct StringOutput { + pub stdout: String, + pub stderr: String, + pub status: ExitStatus, } -/// Executes a git command -#[inline] -pub fn git, S: AsRef>(args: I) -> AppResult { - run_command("git", args) +/// A wrapper around [std::process::Command] with predefined +/// commands used in this project as well as elevated access. +pub struct ShellCommand { + command: String, + args: Vec, + elevated: bool, } -/// Executes a bash command -#[inline] -pub fn bash, S: AsRef>(args: I) -> AppResult { - run_command("bash", args) -} +impl ShellCommand { + pub fn pacman() -> Self { + Self::new("pacman") + } -/// Runs pacman with sudo -pub fn sudo_pacman, S: AsRef>(args: I) -> AppResult { - let mut pacman_args = args - .into_iter() - .map(|i: S| OsString::from(i.as_ref())) - .collect::>(); - let mut sudo_args = vec![OsString::from("pacman")]; - sudo_args.append(&mut pacman_args); - sudo(sudo_args) -} + pub fn makepkg() -> Self { + Self::new("makepkg") + } -/// Executes a pacman command -#[inline] -pub fn pacman, S: AsRef>(args: I) -> AppResult { - run_command("pacman", args) -} + pub fn git() -> Self { + Self::new("git") + } -#[inline] -pub fn sudo, S: AsRef>(args: I) -> AppResult { - run_command("sudo", args) -} + pub fn bash() -> Self { + Self::new("bash") + } -/// Runs a command and parses its output as string -fn run_command, I: IntoIterator, S2: AsRef>( - command: S1, - args: I, -) -> AppResult { - let mut child = Command::new(command) - .args(args) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - let stdout = child.stdout.as_mut().unwrap(); - let stderr = child.stderr.as_mut().unwrap(); - let stdout_str = read_stdout(stdout)?; - let stderr_str = read_stderr(stderr)?; - - let status = child.wait()?; - if status.success() { - Ok(stdout_str) - } else { - Err(AppError::from(stderr_str)) + fn new(command: S) -> Self { + Self { + command: command.to_string(), + args: Vec::new(), + elevated: false, + } } -} -fn read_stdout(stdout: &mut ChildStdout) -> AppResult { - let mut stdout_str = String::new(); - let stdout_reader = BufReader::new(stdout); + /// Adds one argument + pub fn arg>(mut self, arg: S) -> Self { + self.args.push(arg.as_ref().to_os_string()); - for line in stdout_reader.lines() { - let line = line?; - if uwu_enabled() { - println!("{}", uwu!(&*line)) - } else { - println!("{}", &line); - } - stdout_str.push_str(&line); - stdout_str.push_str("\n"); + self } - Ok(stdout_str) -} + /// Adds a list of arguments + pub fn args, S: AsRef>(mut self, args: I) -> Self { + self.args.append( + &mut args + .into_iter() + .map(|a: S| a.as_ref().to_os_string()) + .collect(), + ); -fn read_stderr(stderr: &mut ChildStderr) -> AppResult { - let mut stderr_str = String::new(); - let stderr_reader = BufReader::new(stderr); + self + } - for line in stderr_reader.lines() { - let line = line?; - if uwu_enabled() { - eprintln!("{}", uwu!(&line)) + /// Runs the command with sudo + pub fn elevated(mut self) -> Self { + self.elevated = true; + + self + } + + /// Waits for the child to exit but returns an error when it exists with a non-zero status code + pub fn wait_success(self) -> AppResult<()> { + let status = self.wait()?; + if status.success() { + Ok(()) } else { - eprintln!("{}", &line); + Err(AppError::NonZeroExit) } - stderr_str.push_str(&line); - stderr_str.push_str("\n"); } - Ok(stderr_str) + /// Waits for the child to exit and returns the output status + pub fn wait(self) -> AppResult { + let mut child = self.spawn(false)?; + + child.wait().map_err(AppError::from) + } + + /// Waits with output until the program completed and + /// returns the string output object + pub fn wait_with_output(self) -> AppResult { + let child = self.spawn(true)?; + let output = child.wait_with_output()?; + let stdout = String::from_utf8(output.stdout).map_err(|e| AppError::from(e.to_string()))?; + let stderr = String::from_utf8(output.stderr).map_err(|e| AppError::from(e.to_string()))?; + + Ok(StringOutput { + status: output.status, + stdout, + stderr, + }) + } + + fn spawn(self, piped: bool) -> AppResult { + let (stdout, stderr) = if piped { + (Stdio::piped(), Stdio::piped()) + } else { + (Stdio::inherit(), Stdio::inherit()) + }; + let child = if self.elevated { + Command::new("sudo") + .arg(self.command) + .args(self.args) + .stdout(stdout) + .stderr(stderr) + .spawn()? + } else { + Command::new(self.command) + .args(self.args) + .stdout(stdout) + .stderr(stderr) + .spawn()? + }; + + Ok(child) + } } diff --git a/src/error.rs b/src/internal/error.rs similarity index 74% rename from src/error.rs rename to src/internal/error.rs index 621323a..02e3010 100644 --- a/src/error.rs +++ b/src/internal/error.rs @@ -1,4 +1,5 @@ use crate::crash; +use crate::internal::exit_code::AppExitCode; use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use std::io; @@ -9,6 +10,7 @@ pub type AppResult = Result; pub enum AppError { Io(std::io::Error), Other(String), + NonZeroExit, } impl Display for AppError { @@ -16,6 +18,7 @@ impl Display for AppError { match self { AppError::Io(io) => Display::fmt(io, f), AppError::Other(s) => Display::fmt(s, f), + AppError::NonZeroExit => Display::fmt("exited with non zero code", f), } } } @@ -41,14 +44,14 @@ impl From<&str> for AppError { } pub trait SilentUnwrap { - fn silent_unwrap(self) -> T; + fn silent_unwrap(self, error_code: AppExitCode) -> T; } impl SilentUnwrap for AppResult { - fn silent_unwrap(self) -> T { + fn silent_unwrap(self, exit_code: AppExitCode) -> T { match self { Ok(val) => val, - Err(_) => crash("an error occurred", 1), + Err(_) => crash("an error occurred", exit_code), } } } diff --git a/src/internal/exit_code.rs b/src/internal/exit_code.rs new file mode 100644 index 0000000..aa34dff --- /dev/null +++ b/src/internal/exit_code.rs @@ -0,0 +1,12 @@ +pub enum AppExitCode { + RunAsRoot = 1, + FailedAddingPkg = 2, + FailedInitDb = 3, + FailedCreatingPaths = 4, + MissingDeps = 5, + UserCancellation = 6, + PacmanError = 7, + GitError = 8, + MakePkgError = 9, + Other = 102, +} diff --git a/src/internal/initialise.rs b/src/internal/initialise.rs index 9fe510b..01ee009 100644 --- a/src/internal/initialise.rs +++ b/src/internal/initialise.rs @@ -1,3 +1,4 @@ +use crate::internal::exit_code::AppExitCode; use std::env; use std::path::Path; @@ -19,7 +20,7 @@ pub fn init(options: Options) { Err(e) => { crash( format!("Couldn't create path: {}/.local/share/ame: {}", homedir, e), - 4, + AppExitCode::FailedCreatingPaths, ); } } @@ -40,7 +41,7 @@ pub fn init(options: Options) { Err(e) => { crash( format!("Couldn't create path: {}/.cache/ame: {}", homedir, e), - 4, + AppExitCode::FailedCreatingPaths, ); } } @@ -55,7 +56,7 @@ pub fn init(options: Options) { Err(e) => { crash( format!("Couldn't remove path: {}/.cache/ame: {}", homedir, e), - 4, + AppExitCode::FailedCreatingPaths, ); } } @@ -69,7 +70,7 @@ pub fn init(options: Options) { Err(e2) => { crash( format!("Couldn't create path: {}/.cache/ame: {}", homedir, e2), - 4, + AppExitCode::FailedCreatingPaths, ); } } diff --git a/src/internal/mod.rs b/src/internal/mod.rs index 87bf5d6..fbc6619 100644 --- a/src/internal/mod.rs +++ b/src/internal/mod.rs @@ -1,5 +1,7 @@ mod clean; -mod commands; +pub mod commands; +pub mod error; +pub mod exit_code; mod initialise; pub mod rpc; mod sort; @@ -7,7 +9,6 @@ mod strings; pub mod structs; pub use clean::*; -pub use commands::*; pub use initialise::*; pub use sort::*; use std::env; @@ -30,10 +31,10 @@ macro_rules! uwu { }}; } -fn uwu_enabled() -> bool { +pub fn uwu_enabled() -> bool { env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" } -fn uwu_debug_enabled() -> bool { +pub fn uwu_debug_enabled() -> bool { env::var("AME_UWU_DEBUG").unwrap_or_else(|_| "".to_string()) == "true" } diff --git a/src/internal/strings.rs b/src/internal/strings.rs index 892bb15..3ffe71d 100644 --- a/src/internal/strings.rs +++ b/src/internal/strings.rs @@ -3,25 +3,26 @@ use std::io::Write; use std::process::exit; use std::time::UNIX_EPOCH; +use crate::internal::exit_code::AppExitCode; use crate::{internal, uwu}; -pub fn info(a: S) { - let a = a.to_string(); +pub fn info(msg: S) { + let a = msg.to_string(); let a = if internal::uwu_enabled() { uwu!(&a) } else { a }; println!("\x1b[2;22;35m❖\x1b[0m \x1b[1;37m{}\x1b[0m", a) } -pub fn crash(a: S, b: i32) -> ! { - let a = a.to_string(); +pub fn crash(msg: S, exit_code: AppExitCode) -> ! { + let a = msg.to_string(); let a = if internal::uwu_enabled() { uwu!(&a) } else { a }; println!("\x1b[2;22;31m❌:\x1b[0m \x1b[1;91m{}\x1b[0m", a); - exit(b); + exit(exit_code as i32); } -pub fn log(a: S) { - let a = a.to_string(); +pub fn log(msg: S) { + let a = msg.to_string(); let a = if internal::uwu_enabled() && internal::uwu_debug_enabled() { uwu!(&a) } else { diff --git a/src/main.rs b/src/main.rs index 91471af..4d20366 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,15 +2,17 @@ use clap::Parser; use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs}; use args::Args; +use internal::commands::ShellCommand; +use internal::error::SilentUnwrap; -use crate::internal::{bash, crash, info, init, log, pacman, sort, structs::Options}; +use crate::internal::exit_code::AppExitCode; +use crate::internal::{crash, info, init, log, sort, structs::Options}; #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; mod args; mod database; -mod error; mod internal; mod operations; @@ -20,7 +22,7 @@ fn main() { } if unsafe { geteuid() } == 0 { - crash("Running amethyst as root is disallowed as it can lead to system breakage. Instead, amethyst will prompt you when it needs superuser permissions".to_string(), 1); + crash("Running amethyst as root is disallowed as it can lead to system breakage. Instead, amethyst will prompt you when it needs superuser permissions".to_string(), AppExitCode::RunAsRoot); } let args: Args = Args::parse(); @@ -64,13 +66,21 @@ fn cmd_install(args: InstallArgs, options: Options) { operations::aur_install(sorted.aur, options); } if !sorted.nf.is_empty() { - log(format!( - "Couldn't find packages: {} in repos or the AUR", - sorted.nf.join(", ") - )); + crash( + format!( + "Couldn't find packages: {} in repos or the AUR", + sorted.nf.join(", ") + ), + AppExitCode::PacmanError, + ); } - let bash_output = bash(&["-c", "sudo find /etc -name *.pacnew"]).unwrap(); + let bash_output = ShellCommand::bash() + .arg("-c") + .arg("sudo find /etc -name *.pacnew") + .wait_with_output() + .silent_unwrap(AppExitCode::Other) + .stdout; if !bash_output.is_empty() { let pacnew_files = bash_output @@ -107,13 +117,25 @@ fn cmd_search(args: SearchArgs, options: Options) { fn cmd_query(args: QueryArgs) { if args.aur { - pacman(&["-Qm"]).unwrap(); + ShellCommand::pacman() + .arg("-Qm") + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); } if args.repo { - pacman(&["-Qn"]).unwrap(); + ShellCommand::pacman() + .arg("-Qn") + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); } if !args.repo && !args.aur { - pacman(&["-Qn"]).unwrap(); - pacman(&["-Qm"]).unwrap(); + ShellCommand::pacman() + .arg("-Qn") + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); + ShellCommand::pacman() + .arg("-Qm") + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); } } diff --git a/src/operations/aur_install.rs b/src/operations/aur_install.rs index 659f1c2..9d1be84 100644 --- a/src/operations/aur_install.rs +++ b/src/operations/aur_install.rs @@ -4,10 +4,12 @@ use std::path::Path; use std::process::Command; use std::{env, fs}; -use crate::error::SilentUnwrap; +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::internal::rpc::rpcinfo; -use crate::internal::{crash, git, makepkg, prompt}; -use crate::{bash, info, log, Options}; +use crate::internal::{crash, prompt}; +use crate::{info, log, Options}; pub fn aur_install(a: Vec, options: Options) { let url = crate::internal::rpc::URL; @@ -37,7 +39,11 @@ pub fn aur_install(a: Vec, options: Options) { info("Cloning package source".to_string()); set_current_dir(Path::new(&cachedir)).unwrap(); - git(&["clone", &format!("{}/{}", url, pkg)]).silent_unwrap(); + ShellCommand::git() + .arg("clone") + .arg(format!("{}/{}", url, pkg)) + .wait() + .silent_unwrap(AppExitCode::GitError); if verbosity >= 1 { log(format!( @@ -87,7 +93,7 @@ pub fn aur_install(a: Vec, options: Options) { sorted.nf.join(", "), pkg ), - 5, + AppExitCode::MissingDeps, ); } @@ -109,16 +115,24 @@ pub fn aur_install(a: Vec, options: Options) { .wait() .unwrap(); - let result = bash(&["-c", &format!("ls {}/*.install &> /dev/null", pkg)]); - - if result.is_ok() { - bash(&["-c", &format!("{} {}/*.install", editor, pkg)]).silent_unwrap(); + let status = ShellCommand::bash() + .arg("-c") + .arg(format!("ls {}/*.install &> /dev/null", pkg)) + .wait() + .silent_unwrap(AppExitCode::Other); + + if status.success() { + ShellCommand::bash() + .arg("-c") + .arg(format!("{} {}/*.install", editor, pkg)) + .wait() + .silent_unwrap(AppExitCode::Other); } let p2 = prompt(format!("Would you still like to install {}?", pkg), true); if !p2 { fs::remove_dir_all(format!("{}/{}", cachedir, pkg)).unwrap(); - crash("Not proceeding".to_string(), 6); + crash("Not proceeding".to_string(), AppExitCode::UserCancellation); } } } @@ -145,13 +159,16 @@ pub fn aur_install(a: Vec, options: Options) { // package building and installing info("Building time!".to_string()); set_current_dir(format!("{}/{}", cachedir, pkg)).unwrap(); - let result = makepkg(&makepkg_args); + let status = ShellCommand::makepkg() + .args(makepkg_args) + .wait() + .silent_unwrap(AppExitCode::MakePkgError); - if result.is_ok() { + if !status.success() { fs::remove_dir_all(format!("{}/{}", cachedir, pkg)).unwrap(); crash( format!("Error encountered while installing {}, aborting", pkg), - 7, + AppExitCode::PacmanError, ); } diff --git a/src/operations/install.rs b/src/operations/install.rs index 5c19056..d1f1c59 100644 --- a/src/operations/install.rs +++ b/src/operations/install.rs @@ -1,8 +1,13 @@ -use crate::internal::sudo_pacman; +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::{crash, info, log, Options}; -pub fn install(a: Vec, options: Options) { - info(format!("Installing packages {} from repos", &a.join(", "))); +pub fn install(packages: Vec, options: Options) { + info(format!( + "Installing packages {} from repos", + &packages.join(", ") + )); let mut opers = vec!["-S", "--needed"]; if options.noconfirm { opers.push("--noconfirm"); @@ -11,23 +16,33 @@ pub fn install(a: Vec, options: Options) { opers.push("--asdeps"); } let verbosity = options.verbosity; - if !a.is_empty() { + + if !packages.is_empty() { if verbosity >= 1 { - log(format!("Installing from repos: {:?}", &a)); + log(format!("Installing from repos: {:?}", &packages)); } - if let Err(_e) = sudo_pacman(&opers) { + let status = ShellCommand::pacman() + .elevated() + .args(opers) + .args(&packages) + .wait() + .silent_unwrap(AppExitCode::PacmanError); + if !status.success() { crash( format!( "An error occured while installing packages: {}, aborting", - a.join(", ") + packages.join(", ") ), - 7, + AppExitCode::PacmanError, ); } if verbosity >= 1 { - log(format!("Installing packages: {:?} was successful", &a)); + log(format!( + "Installing packages: {:?} was successful", + &packages + )); } } } diff --git a/src/operations/search.rs b/src/operations/search.rs index 6b0c035..b837133 100644 --- a/src/operations/search.rs +++ b/src/operations/search.rs @@ -1,17 +1,20 @@ -use crate::error::SilentUnwrap; +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::internal::rpc::rpcsearch; -use crate::{log, pacman, Options}; +use crate::{log, Options}; -pub fn aur_search(a: &str, options: Options) { +pub fn aur_search(query: &str, options: Options) { let verbosity = options.verbosity; - let res = rpcsearch(a.to_string()); + let res = rpcsearch(query.to_string()); - for r in &res.results { + for package in &res.results { println!( "aur/{} {}\n {}", - r.name, - r.version, - r.description + package.name, + package.version, + package + .description .as_ref() .unwrap_or(&"No description".to_string()) ) @@ -20,20 +23,27 @@ pub fn aur_search(a: &str, options: Options) { if verbosity >= 1 { log(format!( "Found {} resuls for \"{}\" in AUR", - res.resultcount, a + res.resultcount, query )); } } -pub fn repo_search(a: &str, options: Options) { +pub fn repo_search(query: &str, options: Options) { let verbosity = options.verbosity; - let output = pacman(&["-Ss", a]).silent_unwrap(); + let output = ShellCommand::pacman() + .arg("-Ss") + .arg(query) + .wait_with_output() + .silent_unwrap(AppExitCode::PacmanError) + .stdout; if verbosity >= 1 { log(format!( "Found {} results for \"{}\" in repos", &output.split('\n').count() / 2, - &a + &query )); } + + println!("{}", output) } diff --git a/src/operations/uninstall.rs b/src/operations/uninstall.rs index 1d1700a..e7e51a6 100644 --- a/src/operations/uninstall.rs +++ b/src/operations/uninstall.rs @@ -1,8 +1,9 @@ use std::path::Path; use std::{env, fs}; -use crate::error::SilentUnwrap; -use crate::internal::sudo_pacman; +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::{log, Options}; pub fn uninstall(packages: Vec, options: Options) { @@ -17,7 +18,11 @@ pub fn uninstall(packages: Vec, options: Options) { log(format!("Uninstalling: {:?}", &packages)); } - sudo_pacman(pacman_args).silent_unwrap(); + ShellCommand::pacman() + .elevated() + .args(pacman_args) + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); if verbosity >= 1 { log(format!( diff --git a/src/operations/upgrade.rs b/src/operations/upgrade.rs index a7b8f03..f03d20d 100644 --- a/src/operations/upgrade.rs +++ b/src/operations/upgrade.rs @@ -1,6 +1,7 @@ -use crate::error::SilentUnwrap; +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::internal::rpc::rpcinfo; -use crate::internal::sudo_pacman; use crate::operations::aur_install::aur_install; use crate::{info, log, Options}; @@ -17,7 +18,11 @@ pub fn upgrade(options: Options) { log("Upgrading repo packages".to_string()); } - sudo_pacman(pacman_args).silent_unwrap(); + ShellCommand::pacman() + .elevated() + .args(pacman_args) + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); if verbosity >= 1 { log("Upgrading AUR packages".to_string());