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/args.rs b/src/args.rs index 93a7fe7..0f9ea84 100644 --- a/src/args.rs +++ b/src/args.rs @@ -18,7 +18,7 @@ pub struct Args { #[derive(Debug, Clone, Subcommand)] pub enum Operation { /// Installs a package from either the AUR or the PacMan-defined repositories - #[clap(name="install", aliases=&["i", "-S"])] + #[clap(name="install", aliases=&["i", "ins", "-S"])] Install(InstallArgs), /// Removes a previously installed package diff --git a/src/database/add.rs b/src/database/add.rs index bf4620b..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}; @@ -19,8 +20,7 @@ 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); - 1 - }); + ).unwrap_or_else(|e| + 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 01d92b9..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) { @@ -32,7 +33,9 @@ pub fn init(options: Options) { [], ) .unwrap_or_else(|e| { - crash(format!("Couldn't initialise database: {}", e), 3); - 1 + crash( + format!("Couldn't initialise database: {}", e), + AppExitCode::FailedInitDb, + ) }); } diff --git a/src/internal/commands.rs b/src/internal/commands.rs new file mode 100644 index 0000000..d9270a2 --- /dev/null +++ b/src/internal/commands.rs @@ -0,0 +1,125 @@ +use crate::internal::error::{AppError, AppResult}; +use std::ffi::{OsStr, OsString}; +use std::process::{Child, Command, ExitStatus, Stdio}; + +pub struct StringOutput { + pub stdout: String, + pub stderr: String, + pub status: ExitStatus, +} + +/// 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, +} + +impl ShellCommand { + pub fn pacman() -> Self { + Self::new("pacman") + } + + pub fn makepkg() -> Self { + Self::new("makepkg") + } + + pub fn git() -> Self { + Self::new("git") + } + + pub fn bash() -> Self { + Self::new("bash") + } + + fn new(command: S) -> Self { + Self { + command: command.to_string(), + args: Vec::new(), + elevated: false, + } + } + + /// Adds one argument + pub fn arg>(mut self, arg: S) -> Self { + self.args.push(arg.as_ref().to_os_string()); + + self + } + + /// 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(), + ); + + self + } + + /// 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 { + Err(AppError::NonZeroExit) + } + } + + /// 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/internal/error.rs b/src/internal/error.rs new file mode 100644 index 0000000..02e3010 --- /dev/null +++ b/src/internal/error.rs @@ -0,0 +1,57 @@ +use crate::crash; +use crate::internal::exit_code::AppExitCode; +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; +use std::io; + +pub type AppResult = Result; + +#[derive(Debug)] +pub enum AppError { + Io(std::io::Error), + Other(String), + NonZeroExit, +} + +impl Display for AppError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + 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), + } + } +} + +impl Error for AppError {} + +impl From for AppError { + fn from(e: io::Error) -> Self { + Self::Io(e) + } +} + +impl From for AppError { + fn from(string: String) -> Self { + Self::Other(string) + } +} + +impl From<&str> for AppError { + fn from(string: &str) -> Self { + Self::from(string.to_string()) + } +} + +pub trait SilentUnwrap { + fn silent_unwrap(self, error_code: AppExitCode) -> T; +} + +impl SilentUnwrap for AppResult { + fn silent_unwrap(self, exit_code: AppExitCode) -> T { + match self { + Ok(val) => val, + 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 04b9645..fbc6619 100644 --- a/src/internal/mod.rs +++ b/src/internal/mod.rs @@ -1,4 +1,7 @@ mod clean; +pub mod commands; +pub mod error; +pub mod exit_code; mod initialise; pub mod rpc; mod sort; @@ -8,12 +11,13 @@ pub mod structs; pub use clean::*; pub use initialise::*; pub use sort::*; +use std::env; pub use strings::*; #[macro_export] macro_rules! uwu { ($x:expr) => {{ - let uwu: String = String::from_str($x).unwrap(); + let uwu: String = String::from($x); let uwu = uwu.replace("l", "w"); let uwu = uwu.replace("L", "W"); @@ -26,3 +30,11 @@ macro_rules! uwu { uwu }}; } + +pub fn uwu_enabled() -> bool { + env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" +} + +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 dd2662d..3ffe71d 100644 --- a/src/internal/strings.rs +++ b/src/internal/strings.rs @@ -1,36 +1,29 @@ +use std::io; use std::io::Write; use std::process::exit; -use std::str::FromStr; use std::time::UNIX_EPOCH; -use std::{env, io}; -use crate::uwu; +use crate::internal::exit_code::AppExitCode; +use crate::{internal, uwu}; -pub fn info(a: String) { - let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" { - uwu!(&a) - } else { - a - }; +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: String, b: i32) { - let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" { - uwu!(&a) - } else { - a - }; +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: String) { - let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" - && env::var("AME_UWU_DEBUG").unwrap_or_else(|_| "".to_string()) == "true" - { +pub fn log(msg: S) { + let a = msg.to_string(); + let a = if internal::uwu_enabled() && internal::uwu_debug_enabled() { uwu!(&a) } else { a @@ -46,15 +39,12 @@ pub fn log(a: String) { ); } -pub fn prompt(a: String, b: bool) -> bool { +pub fn prompt(a: S, b: bool) -> bool { + let a = a.to_string(); let default = ["[Y/n]", "[y/N]"]; let i = if b { 0 } else { 1 }; - let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" { - uwu!(&a) - } else { - a - }; + let a = if internal::uwu_enabled() { uwu!(&a) } else { a }; print!( "\x1b[2;22;35m?\x1b[0m \x1b[1;37m{}\x1b[0m \x1b[2;22;37m{}\x1b[0m: ", diff --git a/src/main.rs b/src/main.rs index 24b1c28..4d20366 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ use clap::Parser; -use std::process; -use std::process::Command; use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs}; use args::Args; +use internal::commands::ShellCommand; +use internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::internal::{crash, info, init, log, sort, structs::Options}; #[global_allocator] @@ -21,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(); @@ -65,20 +66,28 @@ 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 out = process::Command::new("bash") - .args(&["-c", "sudo find /etc -name *.pacnew"]) - .output() - .expect("Something has gone wrong") + let bash_output = ShellCommand::bash() + .arg("-c") + .arg("sudo find /etc -name *.pacnew") + .wait_with_output() + .silent_unwrap(AppExitCode::Other) .stdout; - if !String::from_utf8((*out).to_owned()).unwrap().is_empty() { - info(format!("You have .pacnew files in /etc ({}) that you haven't removed or acted upon, it is recommended you do that now", String::from_utf8((*out).to_owned()).unwrap().split_whitespace().collect::>().join(", "))); + if !bash_output.is_empty() { + let pacnew_files = bash_output + .split_whitespace() + .collect::>() + .join(", "); + info(format!("You have .pacnew files in /etc ({pacnew_files}) that you haven't removed or acted upon, it is recommended you do that now", )); } } @@ -108,33 +117,25 @@ fn cmd_search(args: SearchArgs, options: Options) { fn cmd_query(args: QueryArgs) { if args.aur { - Command::new("pacman") + ShellCommand::pacman() .arg("-Qm") - .spawn() - .expect("Something has gone wrong") - .wait() - .unwrap(); + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); } if args.repo { - Command::new("pacman") + ShellCommand::pacman() .arg("-Qn") - .spawn() - .expect("Something has gone wrong") - .wait() - .unwrap(); + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); } if !args.repo && !args.aur { - Command::new("pacman") + ShellCommand::pacman() .arg("-Qn") - .spawn() - .expect("Something has gone wrong") - .wait() - .unwrap(); - Command::new("pacman") + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); + ShellCommand::pacman() .arg("-Qm") - .spawn() - .expect("Something has gone wrong") - .wait() - .unwrap(); + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); } } diff --git a/src/operations/aur_install.rs b/src/operations/aur_install.rs index 130f541..9d1be84 100644 --- a/src/operations/aur_install.rs +++ b/src/operations/aur_install.rs @@ -1,9 +1,12 @@ use std::env::set_current_dir; use std::fs::remove_dir_all; use std::path::Path; -use std::process::{Command, Stdio}; +use std::process::Command; use std::{env, fs}; +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, prompt}; use crate::{info, log, Options}; @@ -36,12 +39,11 @@ pub fn aur_install(a: Vec, options: Options) { info("Cloning package source".to_string()); set_current_dir(Path::new(&cachedir)).unwrap(); - Command::new("git") + ShellCommand::git() .arg("clone") .arg(format!("{}/{}", url, pkg)) - .stdout(Stdio::null()) - .output() - .expect("Something has gone wrong"); + .wait() + .silent_unwrap(AppExitCode::GitError); if verbosity >= 1 { log(format!( @@ -91,7 +93,7 @@ pub fn aur_install(a: Vec, options: Options) { sorted.nf.join(", "), pkg ), - 5, + AppExitCode::MissingDeps, ); } @@ -113,24 +115,24 @@ pub fn aur_install(a: Vec, options: Options) { .wait() .unwrap(); - let out = Command::new("bash") - .args(&["-c", &format!("ls {}/*.install &> /dev/null", pkg)]) - .status() - .unwrap(); + let status = ShellCommand::bash() + .arg("-c") + .arg(format!("ls {}/*.install &> /dev/null", pkg)) + .wait() + .silent_unwrap(AppExitCode::Other); - if out.code() == Some(0) { - Command::new("bash") - .args(&["-c", &format!("{} {}/*.install", editor, pkg)]) - .spawn() - .unwrap() + if status.success() { + ShellCommand::bash() + .arg("-c") + .arg(format!("{} {}/*.install", editor, pkg)) .wait() - .unwrap(); + .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); } } } @@ -157,16 +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 out = Command::new("makepkg") - .args(&makepkg_args) - .status() - .expect("Something has gone wrong"); + let status = ShellCommand::makepkg() + .args(makepkg_args) + .wait() + .silent_unwrap(AppExitCode::MakePkgError); - if out.code() != Some(0) { + 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 cb0aa38..d1f1c59 100644 --- a/src/operations/install.rs +++ b/src/operations/install.rs @@ -1,40 +1,48 @@ +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(", "))); - let mut opers = vec![]; +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".to_string()); + opers.push("--noconfirm"); } if options.asdeps { - opers.push("--asdeps".to_string()); + 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)); } - let r = runas::Command::new("pacman") - .arg("-S") - .arg("--needed") - .args(&a) - .args(&opers) - .status() - .expect("Something has gone wrong"); - - if r.code() != Some(0) { + 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 2056f67..b837133 100644 --- a/src/operations/search.rs +++ b/src/operations/search.rs @@ -1,48 +1,49 @@ -use std::process::Command; - +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::internal::rpc::rpcsearch; 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()); - - if verbosity >= 1 { - log(format!( - "Found {} resuls for \"{}\" in AUR", - res.resultcount, a - )); - } + 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()) ) } + + if verbosity >= 1 { + log(format!( + "Found {} resuls for \"{}\" in AUR", + res.resultcount, query + )); + } } -pub fn repo_search(a: &str, options: Options) { +pub fn repo_search(query: &str, options: Options) { let verbosity = options.verbosity; - let rs = Command::new("pacman") + let output = ShellCommand::pacman() .arg("-Ss") - .arg(&a) - .output() - .expect("Something has gone wrong"); - - let str = String::from_utf8(rs.stdout).unwrap(); + .arg(query) + .wait_with_output() + .silent_unwrap(AppExitCode::PacmanError) + .stdout; if verbosity >= 1 { log(format!( "Found {} results for \"{}\" in repos", - &str.split('\n').count() / 2, - &a + &output.split('\n').count() / 2, + &query )); } - print!("{}", str); + println!("{}", output) } diff --git a/src/operations/uninstall.rs b/src/operations/uninstall.rs index 0e2ef05..e7e51a6 100644 --- a/src/operations/uninstall.rs +++ b/src/operations/uninstall.rs @@ -1,43 +1,52 @@ use std::path::Path; use std::{env, fs}; +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::{log, Options}; -pub fn uninstall(mut a: Vec, options: Options) { - let b = a.clone(); +pub fn uninstall(packages: Vec, options: Options) { + let mut pacman_args = vec!["-Rs"]; + pacman_args.append(&mut packages.iter().map(|s| s.as_str()).collect()); + if options.noconfirm { - a.push("--noconfirm".to_string()); + pacman_args.push("--noconfirm"); } let verbosity = options.verbosity; if verbosity >= 1 { - log(format!("Uninstalling: {:?}", &b)); + log(format!("Uninstalling: {:?}", &packages)); } - let r = runas::Command::new("pacman") - .arg("-Rs") - .args(&a) - .status() - .expect("Something has gone wrong"); + ShellCommand::pacman() + .elevated() + .args(pacman_args) + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); - if let Some(x) = r.code() { - if verbosity >= 1 { - log(format!( - "Uninstalling packages: {:?} exited with code {}", - &b, x - )); - } + if verbosity >= 1 { + log(format!( + "Uninstalling packages: {:?} exited with code 0", + &packages + )); } - for b in a { - crate::database::remove(&b, options); - if Path::new(&format!("{}/.cache/ame/{}", env::var("HOME").unwrap(), b)).exists() { + for package in packages { + crate::database::remove(&package, options); + if Path::new(&format!( + "{}/.cache/ame/{}", + env::var("HOME").unwrap(), + package + )) + .exists() + { if verbosity >= 1 { log("Old cache directory found, deleting".to_string()); } fs::remove_dir_all(Path::new(&format!( "{}/.cache/ame/{}", env::var("HOME").unwrap(), - b + package ))) .unwrap(); } diff --git a/src/operations/upgrade.rs b/src/operations/upgrade.rs index d80c824..f03d20d 100644 --- a/src/operations/upgrade.rs +++ b/src/operations/upgrade.rs @@ -1,5 +1,6 @@ -use runas::Command; - +use crate::internal::commands::ShellCommand; +use crate::internal::error::SilentUnwrap; +use crate::internal::exit_code::AppExitCode; use crate::internal::rpc::rpcinfo; use crate::operations::aur_install::aur_install; use crate::{info, log, Options}; @@ -17,10 +18,11 @@ pub fn upgrade(options: Options) { log("Upgrading repo packages".to_string()); } - Command::new("pacman") - .args(&pacman_args) - .status() - .expect("Something has gone wrong"); + ShellCommand::pacman() + .elevated() + .args(pacman_args) + .wait_success() + .silent_unwrap(AppExitCode::PacmanError); if verbosity >= 1 { log("Upgrading AUR packages".to_string());