Wrap commands with ShellCommand builder

Signed-off-by: Trivernis <trivernis@protonmail.com>
i18n
Trivernis 2 years ago
parent 2266b10a7b
commit b8507025f6

@ -53,7 +53,6 @@ codegen-units = 1
mimalloc = { version = "0.1.27", default-features = false } mimalloc = { version = "0.1.27", default-features = false }
clap = { version = "3.1.9", features = [ "derive", "wrap_help"] } clap = { version = "3.1.9", features = [ "derive", "wrap_help"] }
regex = { version = "1.5.4", default-features = false, features = ["std", "unicode-perl"] } regex = { version = "1.5.4", default-features = false, features = ["std", "unicode-perl"] }
runas = "0.2.1"
rusqlite = { version = "0.26.3", default-features = false } rusqlite = { version = "0.26.3", default-features = false }
ureq = { version = "2.4.0", default-features = false, features = ["native-tls", "json"] } ureq = { version = "2.4.0", default-features = false, features = ["native-tls", "json"] }
serde = { version = "1.0.90", default-features = false, features = ["derive", "serde_derive"] } serde = { version = "1.0.90", default-features = false, features = ["derive", "serde_derive"] }

@ -3,6 +3,7 @@ use std::path::Path;
use rusqlite::Connection; use rusqlite::Connection;
use crate::internal::exit_code::AppExitCode;
use crate::internal::rpc::Package; use crate::internal::rpc::Package;
use crate::{crash, log, Options}; 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)", 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(" ")], [&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| ).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)
); );
} }

@ -3,6 +3,7 @@ use std::path::Path;
use rusqlite::Connection; use rusqlite::Connection;
use crate::internal::exit_code::AppExitCode;
use crate::{crash, log, Options}; use crate::{crash, log, Options};
pub fn init(options: 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,
)
});
} }

@ -1,105 +1,125 @@
use crate::error::{AppError, AppResult}; use crate::internal::error::{AppError, AppResult};
use crate::internal::uwu_enabled;
use crate::uwu;
use std::ffi::{OsStr, OsString}; use std::ffi::{OsStr, OsString};
use std::io::{BufRead, BufReader}; use std::process::{Child, Command, ExitStatus, Stdio};
use std::process::{ChildStderr, ChildStdout, Command, Stdio};
/// Executes a makepkg command pub struct StringOutput {
#[inline] pub stdout: String,
pub fn makepkg<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> { pub stderr: String,
run_command("makepkg", args) pub status: ExitStatus,
} }
/// Executes a git command /// A wrapper around [std::process::Command] with predefined
#[inline] /// commands used in this project as well as elevated access.
pub fn git<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> { pub struct ShellCommand {
run_command("git", args) command: String,
args: Vec<OsString>,
elevated: bool,
} }
/// Executes a bash command impl ShellCommand {
#[inline] pub fn pacman() -> Self {
pub fn bash<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> { Self::new("pacman")
run_command("bash", args) }
}
/// Runs pacman with sudo pub fn makepkg() -> Self {
pub fn sudo_pacman<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> { Self::new("makepkg")
let mut pacman_args = args }
.into_iter()
.map(|i: S| OsString::from(i.as_ref()))
.collect::<Vec<OsString>>();
let mut sudo_args = vec![OsString::from("pacman")];
sudo_args.append(&mut pacman_args);
sudo(sudo_args)
}
/// Executes a pacman command pub fn git() -> Self {
#[inline] Self::new("git")
pub fn pacman<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> { }
run_command("pacman", args)
}
#[inline] pub fn bash() -> Self {
pub fn sudo<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> { Self::new("bash")
run_command("sudo", args) }
}
/// Runs a command and parses its output as string fn new<S: ToString>(command: S) -> Self {
fn run_command<S1: AsRef<OsStr>, I: IntoIterator<Item = S2>, S2: AsRef<OsStr>>( Self {
command: S1, command: command.to_string(),
args: I, args: Vec::new(),
) -> AppResult<String> { elevated: false,
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 read_stdout(stdout: &mut ChildStdout) -> AppResult<String> { /// Adds one argument
let mut stdout_str = String::new(); pub fn arg<S: AsRef<OsStr>>(mut self, arg: S) -> Self {
let stdout_reader = BufReader::new(stdout); self.args.push(arg.as_ref().to_os_string());
for line in stdout_reader.lines() { self
let line = line?;
if uwu_enabled() {
println!("{}", uwu!(&*line))
} else {
println!("{}", &line);
}
stdout_str.push_str(&line);
stdout_str.push_str("\n");
} }
Ok(stdout_str) /// Adds a list of arguments
} pub fn args<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(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<String> { self
let mut stderr_str = String::new(); }
let stderr_reader = BufReader::new(stderr);
for line in stderr_reader.lines() { /// Runs the command with sudo
let line = line?; pub fn elevated(mut self) -> Self {
if uwu_enabled() { self.elevated = true;
eprintln!("{}", uwu!(&line))
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 { } 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<ExitStatus> {
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<StringOutput> {
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<Child> {
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)
}
} }

@ -1,4 +1,5 @@
use crate::crash; use crate::crash;
use crate::internal::exit_code::AppExitCode;
use std::error::Error; use std::error::Error;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::io; use std::io;
@ -9,6 +10,7 @@ pub type AppResult<T> = Result<T, AppError>;
pub enum AppError { pub enum AppError {
Io(std::io::Error), Io(std::io::Error),
Other(String), Other(String),
NonZeroExit,
} }
impl Display for AppError { impl Display for AppError {
@ -16,6 +18,7 @@ impl Display for AppError {
match self { match self {
AppError::Io(io) => Display::fmt(io, f), AppError::Io(io) => Display::fmt(io, f),
AppError::Other(s) => Display::fmt(s, 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<T> { pub trait SilentUnwrap<T> {
fn silent_unwrap(self) -> T; fn silent_unwrap(self, error_code: AppExitCode) -> T;
} }
impl<T> SilentUnwrap<T> for AppResult<T> { impl<T> SilentUnwrap<T> for AppResult<T> {
fn silent_unwrap(self) -> T { fn silent_unwrap(self, exit_code: AppExitCode) -> T {
match self { match self {
Ok(val) => val, Ok(val) => val,
Err(_) => crash("an error occurred", 1), Err(_) => crash("an error occurred", exit_code),
} }
} }
} }

@ -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,
}

@ -1,3 +1,4 @@
use crate::internal::exit_code::AppExitCode;
use std::env; use std::env;
use std::path::Path; use std::path::Path;
@ -19,7 +20,7 @@ pub fn init(options: Options) {
Err(e) => { Err(e) => {
crash( crash(
format!("Couldn't create path: {}/.local/share/ame: {}", homedir, e), format!("Couldn't create path: {}/.local/share/ame: {}", homedir, e),
4, AppExitCode::FailedCreatingPaths,
); );
} }
} }
@ -40,7 +41,7 @@ pub fn init(options: Options) {
Err(e) => { Err(e) => {
crash( crash(
format!("Couldn't create path: {}/.cache/ame: {}", homedir, e), format!("Couldn't create path: {}/.cache/ame: {}", homedir, e),
4, AppExitCode::FailedCreatingPaths,
); );
} }
} }
@ -55,7 +56,7 @@ pub fn init(options: Options) {
Err(e) => { Err(e) => {
crash( crash(
format!("Couldn't remove path: {}/.cache/ame: {}", homedir, e), format!("Couldn't remove path: {}/.cache/ame: {}", homedir, e),
4, AppExitCode::FailedCreatingPaths,
); );
} }
} }
@ -69,7 +70,7 @@ pub fn init(options: Options) {
Err(e2) => { Err(e2) => {
crash( crash(
format!("Couldn't create path: {}/.cache/ame: {}", homedir, e2), format!("Couldn't create path: {}/.cache/ame: {}", homedir, e2),
4, AppExitCode::FailedCreatingPaths,
); );
} }
} }

@ -1,5 +1,7 @@
mod clean; mod clean;
mod commands; pub mod commands;
pub mod error;
pub mod exit_code;
mod initialise; mod initialise;
pub mod rpc; pub mod rpc;
mod sort; mod sort;
@ -7,7 +9,6 @@ mod strings;
pub mod structs; pub mod structs;
pub use clean::*; pub use clean::*;
pub use commands::*;
pub use initialise::*; pub use initialise::*;
pub use sort::*; pub use sort::*;
use std::env; 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" 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" env::var("AME_UWU_DEBUG").unwrap_or_else(|_| "".to_string()) == "true"
} }

@ -3,25 +3,26 @@ use std::io::Write;
use std::process::exit; use std::process::exit;
use std::time::UNIX_EPOCH; use std::time::UNIX_EPOCH;
use crate::internal::exit_code::AppExitCode;
use crate::{internal, uwu}; use crate::{internal, uwu};
pub fn info<S: ToString>(a: S) { pub fn info<S: ToString>(msg: S) {
let a = a.to_string(); let a = msg.to_string();
let a = if internal::uwu_enabled() { uwu!(&a) } else { a }; let a = if internal::uwu_enabled() { uwu!(&a) } else { a };
println!("\x1b[2;22;35m❖\x1b[0m \x1b[1;37m{}\x1b[0m", a) println!("\x1b[2;22;35m❖\x1b[0m \x1b[1;37m{}\x1b[0m", a)
} }
pub fn crash<S: ToString>(a: S, b: i32) -> ! { pub fn crash<S: ToString>(msg: S, exit_code: AppExitCode) -> ! {
let a = a.to_string(); let a = msg.to_string();
let a = if internal::uwu_enabled() { uwu!(&a) } else { a }; let a = if internal::uwu_enabled() { uwu!(&a) } else { a };
println!("\x1b[2;22;31m❌:\x1b[0m \x1b[1;91m{}\x1b[0m", a); println!("\x1b[2;22;31m❌:\x1b[0m \x1b[1;91m{}\x1b[0m", a);
exit(b); exit(exit_code as i32);
} }
pub fn log<S: ToString>(a: S) { pub fn log<S: ToString>(msg: S) {
let a = a.to_string(); let a = msg.to_string();
let a = if internal::uwu_enabled() && internal::uwu_debug_enabled() { let a = if internal::uwu_enabled() && internal::uwu_debug_enabled() {
uwu!(&a) uwu!(&a)
} else { } else {

@ -2,15 +2,17 @@ use clap::Parser;
use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs}; use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs};
use args::Args; 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] #[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
mod args; mod args;
mod database; mod database;
mod error;
mod internal; mod internal;
mod operations; mod operations;
@ -20,7 +22,7 @@ fn main() {
} }
if unsafe { geteuid() } == 0 { 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(); let args: Args = Args::parse();
@ -64,13 +66,21 @@ fn cmd_install(args: InstallArgs, options: Options) {
operations::aur_install(sorted.aur, options); operations::aur_install(sorted.aur, options);
} }
if !sorted.nf.is_empty() { if !sorted.nf.is_empty() {
log(format!( crash(
"Couldn't find packages: {} in repos or the AUR", format!(
sorted.nf.join(", ") "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() { if !bash_output.is_empty() {
let pacnew_files = bash_output let pacnew_files = bash_output
@ -107,13 +117,25 @@ fn cmd_search(args: SearchArgs, options: Options) {
fn cmd_query(args: QueryArgs) { fn cmd_query(args: QueryArgs) {
if args.aur { if args.aur {
pacman(&["-Qm"]).unwrap(); ShellCommand::pacman()
.arg("-Qm")
.wait_success()
.silent_unwrap(AppExitCode::PacmanError);
} }
if args.repo { if args.repo {
pacman(&["-Qn"]).unwrap(); ShellCommand::pacman()
.arg("-Qn")
.wait_success()
.silent_unwrap(AppExitCode::PacmanError);
} }
if !args.repo && !args.aur { if !args.repo && !args.aur {
pacman(&["-Qn"]).unwrap(); ShellCommand::pacman()
pacman(&["-Qm"]).unwrap(); .arg("-Qn")
.wait_success()
.silent_unwrap(AppExitCode::PacmanError);
ShellCommand::pacman()
.arg("-Qm")
.wait_success()
.silent_unwrap(AppExitCode::PacmanError);
} }
} }

@ -4,10 +4,12 @@ use std::path::Path;
use std::process::Command; use std::process::Command;
use std::{env, fs}; 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::rpc::rpcinfo;
use crate::internal::{crash, git, makepkg, prompt}; use crate::internal::{crash, prompt};
use crate::{bash, info, log, Options}; use crate::{info, log, Options};
pub fn aur_install(a: Vec<String>, options: Options) { pub fn aur_install(a: Vec<String>, options: Options) {
let url = crate::internal::rpc::URL; let url = crate::internal::rpc::URL;
@ -37,7 +39,11 @@ pub fn aur_install(a: Vec<String>, options: Options) {
info("Cloning package source".to_string()); info("Cloning package source".to_string());
set_current_dir(Path::new(&cachedir)).unwrap(); 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 { if verbosity >= 1 {
log(format!( log(format!(
@ -87,7 +93,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
sorted.nf.join(", "), sorted.nf.join(", "),
pkg pkg
), ),
5, AppExitCode::MissingDeps,
); );
} }
@ -109,16 +115,24 @@ pub fn aur_install(a: Vec<String>, options: Options) {
.wait() .wait()
.unwrap(); .unwrap();
let result = bash(&["-c", &format!("ls {}/*.install &> /dev/null", pkg)]); let status = ShellCommand::bash()
.arg("-c")
if result.is_ok() { .arg(format!("ls {}/*.install &> /dev/null", pkg))
bash(&["-c", &format!("{} {}/*.install", editor, pkg)]).silent_unwrap(); .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); let p2 = prompt(format!("Would you still like to install {}?", pkg), true);
if !p2 { if !p2 {
fs::remove_dir_all(format!("{}/{}", cachedir, pkg)).unwrap(); 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<String>, options: Options) {
// package building and installing // package building and installing
info("Building time!".to_string()); info("Building time!".to_string());
set_current_dir(format!("{}/{}", cachedir, pkg)).unwrap(); 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(); fs::remove_dir_all(format!("{}/{}", cachedir, pkg)).unwrap();
crash( crash(
format!("Error encountered while installing {}, aborting", pkg), format!("Error encountered while installing {}, aborting", pkg),
7, AppExitCode::PacmanError,
); );
} }

@ -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}; use crate::{crash, info, log, Options};
pub fn install(a: Vec<String>, options: Options) { pub fn install(packages: Vec<String>, options: Options) {
info(format!("Installing packages {} from repos", &a.join(", "))); info(format!(
"Installing packages {} from repos",
&packages.join(", ")
));
let mut opers = vec!["-S", "--needed"]; let mut opers = vec!["-S", "--needed"];
if options.noconfirm { if options.noconfirm {
opers.push("--noconfirm"); opers.push("--noconfirm");
@ -11,23 +16,33 @@ pub fn install(a: Vec<String>, options: Options) {
opers.push("--asdeps"); opers.push("--asdeps");
} }
let verbosity = options.verbosity; let verbosity = options.verbosity;
if !a.is_empty() {
if !packages.is_empty() {
if verbosity >= 1 { 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( crash(
format!( format!(
"An error occured while installing packages: {}, aborting", "An error occured while installing packages: {}, aborting",
a.join(", ") packages.join(", ")
), ),
7, AppExitCode::PacmanError,
); );
} }
if verbosity >= 1 { if verbosity >= 1 {
log(format!("Installing packages: {:?} was successful", &a)); log(format!(
"Installing packages: {:?} was successful",
&packages
));
} }
} }
} }

@ -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::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 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!( println!(
"aur/{} {}\n {}", "aur/{} {}\n {}",
r.name, package.name,
r.version, package.version,
r.description package
.description
.as_ref() .as_ref()
.unwrap_or(&"No description".to_string()) .unwrap_or(&"No description".to_string())
) )
@ -20,20 +23,27 @@ pub fn aur_search(a: &str, options: Options) {
if verbosity >= 1 { if verbosity >= 1 {
log(format!( log(format!(
"Found {} resuls for \"{}\" in AUR", "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 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 { if verbosity >= 1 {
log(format!( log(format!(
"Found {} results for \"{}\" in repos", "Found {} results for \"{}\" in repos",
&output.split('\n').count() / 2, &output.split('\n').count() / 2,
&a &query
)); ));
} }
println!("{}", output)
} }

@ -1,8 +1,9 @@
use std::path::Path; use std::path::Path;
use std::{env, fs}; use std::{env, fs};
use crate::error::SilentUnwrap; use crate::internal::commands::ShellCommand;
use crate::internal::sudo_pacman; use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode;
use crate::{log, Options}; use crate::{log, Options};
pub fn uninstall(packages: Vec<String>, options: Options) { pub fn uninstall(packages: Vec<String>, options: Options) {
@ -17,7 +18,11 @@ pub fn uninstall(packages: Vec<String>, options: Options) {
log(format!("Uninstalling: {:?}", &packages)); 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 { if verbosity >= 1 {
log(format!( log(format!(

@ -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::rpc::rpcinfo;
use crate::internal::sudo_pacman;
use crate::operations::aur_install::aur_install; use crate::operations::aur_install::aur_install;
use crate::{info, log, Options}; use crate::{info, log, Options};
@ -17,7 +18,11 @@ pub fn upgrade(options: Options) {
log("Upgrading repo packages".to_string()); 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 { if verbosity >= 1 {
log("Upgrading AUR packages".to_string()); log("Upgrading AUR packages".to_string());

Loading…
Cancel
Save