Encapsulate command executions

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

@ -19,8 +19,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)", 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), 2)
1 );
});
} }

@ -31,8 +31,5 @@ pub fn init(options: Options) {
)", )",
[], [],
) )
.unwrap_or_else(|e| { .unwrap_or_else(|e| crash(format!("Couldn't initialise database: {}", e), 3));
crash(format!("Couldn't initialise database: {}", e), 3);
1
});
} }

@ -0,0 +1,54 @@
use crate::crash;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::io;
pub type AppResult<T> = Result<T, AppError>;
#[derive(Debug)]
pub enum AppError {
Io(std::io::Error),
Other(String),
}
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),
}
}
}
impl Error for AppError {}
impl From<io::Error> for AppError {
fn from(e: io::Error) -> Self {
Self::Io(e)
}
}
impl From<String> 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<T> {
fn silent_unwrap(self) -> T;
}
impl<T> SilentUnwrap<T> for AppResult<T> {
fn silent_unwrap(self) -> T {
match self {
Ok(val) => val,
Err(_) => crash("an error occurred", 1),
}
}
}

@ -0,0 +1,105 @@
use crate::error::{AppError, AppResult};
use crate::internal::uwu_enabled;
use crate::uwu;
use std::ffi::{OsStr, OsString};
use std::io::{BufRead, BufReader};
use std::process::{ChildStderr, ChildStdout, Command, Stdio};
/// Executes a makepkg command
#[inline]
pub fn makepkg<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> {
run_command("makepkg", args)
}
/// Executes a git command
#[inline]
pub fn git<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> {
run_command("git", args)
}
/// Executes a bash command
#[inline]
pub fn bash<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> {
run_command("bash", args)
}
/// Runs pacman with sudo
pub fn sudo_pacman<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> {
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
#[inline]
pub fn pacman<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> {
run_command("pacman", args)
}
#[inline]
pub fn sudo<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(args: I) -> AppResult<String> {
run_command("sudo", args)
}
/// Runs a command and parses its output as string
fn run_command<S1: AsRef<OsStr>, I: IntoIterator<Item = S2>, S2: AsRef<OsStr>>(
command: S1,
args: I,
) -> AppResult<String> {
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> {
let mut stdout_str = String::new();
let stdout_reader = BufReader::new(stdout);
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");
}
Ok(stdout_str)
}
fn read_stderr(stderr: &mut ChildStderr) -> AppResult<String> {
let mut stderr_str = String::new();
let stderr_reader = BufReader::new(stderr);
for line in stderr_reader.lines() {
let line = line?;
if uwu_enabled() {
eprintln!("{}", uwu!(&line))
} else {
eprintln!("{}", &line);
}
stderr_str.push_str(&line);
stderr_str.push_str("\n");
}
Ok(stderr_str)
}

@ -1,4 +1,5 @@
mod clean; mod clean;
mod commands;
mod initialise; mod initialise;
pub mod rpc; pub mod rpc;
mod sort; mod sort;
@ -6,14 +7,16 @@ 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;
pub use strings::*; pub use strings::*;
#[macro_export] #[macro_export]
macro_rules! uwu { macro_rules! uwu {
($x:expr) => {{ ($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");
let uwu = uwu.replace("L", "W"); let uwu = uwu.replace("L", "W");
@ -26,3 +29,11 @@ macro_rules! uwu {
uwu uwu
}}; }};
} }
fn uwu_enabled() -> bool {
env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true"
}
fn uwu_debug_enabled() -> bool {
env::var("AME_UWU_DEBUG").unwrap_or_else(|_| "".to_string()) == "true"
}

@ -1,36 +1,28 @@
use std::io;
use std::io::Write; use std::io::Write;
use std::process::exit; use std::process::exit;
use std::str::FromStr;
use std::time::UNIX_EPOCH; use std::time::UNIX_EPOCH;
use std::{env, io};
use crate::uwu; use crate::{internal, uwu};
pub fn info(a: String) { pub fn info<S: ToString>(a: S) {
let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" { let a = a.to_string();
uwu!(&a) let a = if internal::uwu_enabled() { uwu!(&a) } else { 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(a: String, b: i32) { pub fn crash<S: ToString>(a: S, b: i32) -> ! {
let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" { let a = a.to_string();
uwu!(&a) let a = if internal::uwu_enabled() { uwu!(&a) } else { 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(b);
} }
pub fn log(a: String) { pub fn log<S: ToString>(a: S) {
let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" let a = a.to_string();
&& env::var("AME_UWU_DEBUG").unwrap_or_else(|_| "".to_string()) == "true" let a = if internal::uwu_enabled() && internal::uwu_debug_enabled() {
{
uwu!(&a) uwu!(&a)
} else { } else {
a a
@ -46,15 +38,12 @@ pub fn log(a: String) {
); );
} }
pub fn prompt(a: String, b: bool) -> bool { pub fn prompt<S: ToString>(a: S, b: bool) -> bool {
let a = a.to_string();
let default = ["[Y/n]", "[y/N]"]; let default = ["[Y/n]", "[y/N]"];
let i = if b { 0 } else { 1 }; let i = if b { 0 } else { 1 };
let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" { let a = if internal::uwu_enabled() { uwu!(&a) } else { a };
uwu!(&a)
} else {
a
};
print!( print!(
"\x1b[2;22;35m?\x1b[0m \x1b[1;37m{}\x1b[0m \x1b[2;22;37m{}\x1b[0m: ", "\x1b[2;22;35m?\x1b[0m \x1b[1;37m{}\x1b[0m \x1b[2;22;37m{}\x1b[0m: ",

@ -1,17 +1,16 @@
use clap::Parser; use clap::Parser;
use std::process;
use std::process::Command;
use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs}; use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs};
use args::Args; use args::Args;
use crate::internal::{crash, info, init, log, sort, structs::Options}; use crate::internal::{bash, crash, info, init, log, pacman, 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;
@ -71,14 +70,14 @@ fn cmd_install(args: InstallArgs, options: Options) {
)); ));
} }
let out = process::Command::new("bash") let bash_output = bash(&["-c", "sudo find /etc -name *.pacnew"]).unwrap();
.args(&["-c", "sudo find /etc -name *.pacnew"])
.output()
.expect("Something has gone wrong")
.stdout;
if !String::from_utf8((*out).to_owned()).unwrap().is_empty() { if !bash_output.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::<Vec<&str>>().join(", "))); let pacnew_files = bash_output
.split_whitespace()
.collect::<Vec<&str>>()
.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 +107,13 @@ fn cmd_search(args: SearchArgs, options: Options) {
fn cmd_query(args: QueryArgs) { fn cmd_query(args: QueryArgs) {
if args.aur { if args.aur {
Command::new("pacman") pacman(&["-Qm"]).unwrap();
.arg("-Qm")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
} }
if args.repo { if args.repo {
Command::new("pacman") pacman(&["-Qn"]).unwrap();
.arg("-Qn")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
} }
if !args.repo && !args.aur { if !args.repo && !args.aur {
Command::new("pacman") pacman(&["-Qn"]).unwrap();
.arg("-Qn") pacman(&["-Qm"]).unwrap();
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
Command::new("pacman")
.arg("-Qm")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
} }
} }

@ -1,12 +1,13 @@
use std::env::set_current_dir; use std::env::set_current_dir;
use std::fs::remove_dir_all; use std::fs::remove_dir_all;
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio}; use std::process::Command;
use std::{env, fs}; use std::{env, fs};
use crate::error::SilentUnwrap;
use crate::internal::rpc::rpcinfo; use crate::internal::rpc::rpcinfo;
use crate::internal::{crash, prompt}; use crate::internal::{crash, git, makepkg, prompt};
use crate::{info, log, Options}; use crate::{bash, 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;
@ -36,12 +37,7 @@ 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();
Command::new("git") git(&["clone", &format!("{}/{}", url, pkg)]).silent_unwrap();
.arg("clone")
.arg(format!("{}/{}", url, pkg))
.stdout(Stdio::null())
.output()
.expect("Something has gone wrong");
if verbosity >= 1 { if verbosity >= 1 {
log(format!( log(format!(
@ -113,18 +109,10 @@ pub fn aur_install(a: Vec<String>, options: Options) {
.wait() .wait()
.unwrap(); .unwrap();
let out = Command::new("bash") let result = bash(&["-c", &format!("ls {}/*.install &> /dev/null", pkg)]);
.args(&["-c", &format!("ls {}/*.install &> /dev/null", pkg)])
.status()
.unwrap();
if out.code() == Some(0) { if result.is_ok() {
Command::new("bash") bash(&["-c", &format!("{} {}/*.install", editor, pkg)]).silent_unwrap();
.args(&["-c", &format!("{} {}/*.install", editor, pkg)])
.spawn()
.unwrap()
.wait()
.unwrap();
} }
let p2 = prompt(format!("Would you still like to install {}?", pkg), true); let p2 = prompt(format!("Would you still like to install {}?", pkg), true);
@ -157,12 +145,9 @@ 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 out = Command::new("makepkg") let result = makepkg(&makepkg_args);
.args(&makepkg_args)
.status()
.expect("Something has gone wrong");
if out.code() != Some(0) { if result.is_ok() {
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),

@ -1,13 +1,14 @@
use crate::internal::sudo_pacman;
use crate::{crash, info, log, Options}; use crate::{crash, info, log, Options};
pub fn install(a: Vec<String>, options: Options) { pub fn install(a: Vec<String>, options: Options) {
info(format!("Installing packages {} from repos", &a.join(", "))); info(format!("Installing packages {} from repos", &a.join(", ")));
let mut opers = vec![]; let mut opers = vec!["-S", "--needed"];
if options.noconfirm { if options.noconfirm {
opers.push("--noconfirm".to_string()); opers.push("--noconfirm");
} }
if options.asdeps { if options.asdeps {
opers.push("--asdeps".to_string()); opers.push("--asdeps");
} }
let verbosity = options.verbosity; let verbosity = options.verbosity;
if !a.is_empty() { if !a.is_empty() {
@ -15,15 +16,7 @@ pub fn install(a: Vec<String>, options: Options) {
log(format!("Installing from repos: {:?}", &a)); log(format!("Installing from repos: {:?}", &a));
} }
let r = runas::Command::new("pacman") if let Err(_e) = sudo_pacman(&opers) {
.arg("-S")
.arg("--needed")
.args(&a)
.args(&opers)
.status()
.expect("Something has gone wrong");
if r.code() != Some(0) {
crash( crash(
format!( format!(
"An error occured while installing packages: {}, aborting", "An error occured while installing packages: {}, aborting",

@ -1,19 +1,11 @@
use std::process::Command; use crate::error::SilentUnwrap;
use crate::internal::rpc::rpcsearch; use crate::internal::rpc::rpcsearch;
use crate::{log, Options}; use crate::{log, pacman, Options};
pub fn aur_search(a: &str, options: Options) { pub fn aur_search(a: &str, options: Options) {
let verbosity = options.verbosity; let verbosity = options.verbosity;
let res = rpcsearch(a.to_string()); let res = rpcsearch(a.to_string());
if verbosity >= 1 {
log(format!(
"Found {} resuls for \"{}\" in AUR",
res.resultcount, a
));
}
for r in &res.results { for r in &res.results {
println!( println!(
"aur/{} {}\n {}", "aur/{} {}\n {}",
@ -24,25 +16,24 @@ pub fn aur_search(a: &str, options: Options) {
.unwrap_or(&"No description".to_string()) .unwrap_or(&"No description".to_string())
) )
} }
if verbosity >= 1 {
log(format!(
"Found {} resuls for \"{}\" in AUR",
res.resultcount, a
));
}
} }
pub fn repo_search(a: &str, options: Options) { pub fn repo_search(a: &str, options: Options) {
let verbosity = options.verbosity; let verbosity = options.verbosity;
let rs = Command::new("pacman") let output = pacman(&["-Ss", a]).silent_unwrap();
.arg("-Ss")
.arg(&a)
.output()
.expect("Something has gone wrong");
let str = String::from_utf8(rs.stdout).unwrap();
if verbosity >= 1 { if verbosity >= 1 {
log(format!( log(format!(
"Found {} results for \"{}\" in repos", "Found {} results for \"{}\" in repos",
&str.split('\n').count() / 2, &output.split('\n').count() / 2,
&a &a
)); ));
} }
print!("{}", str);
} }

@ -1,43 +1,47 @@
use std::path::Path; use std::path::Path;
use std::{env, fs}; use std::{env, fs};
use crate::error::SilentUnwrap;
use crate::internal::sudo_pacman;
use crate::{log, Options}; use crate::{log, Options};
pub fn uninstall(mut a: Vec<String>, options: Options) { pub fn uninstall(packages: Vec<String>, options: Options) {
let b = a.clone(); let mut pacman_args = vec!["-Rs"];
pacman_args.append(&mut packages.iter().map(|s| s.as_str()).collect());
if options.noconfirm { if options.noconfirm {
a.push("--noconfirm".to_string()); pacman_args.push("--noconfirm");
} }
let verbosity = options.verbosity; let verbosity = options.verbosity;
if verbosity >= 1 { if verbosity >= 1 {
log(format!("Uninstalling: {:?}", &b)); log(format!("Uninstalling: {:?}", &packages));
} }
let r = runas::Command::new("pacman") sudo_pacman(pacman_args).silent_unwrap();
.arg("-Rs")
.args(&a)
.status()
.expect("Something has gone wrong");
if let Some(x) = r.code() { if verbosity >= 1 {
if verbosity >= 1 { log(format!(
log(format!( "Uninstalling packages: {:?} exited with code 0",
"Uninstalling packages: {:?} exited with code {}", &packages
&b, x ));
));
}
} }
for b in a { for package in packages {
crate::database::remove(&b, options); crate::database::remove(&package, options);
if Path::new(&format!("{}/.cache/ame/{}", env::var("HOME").unwrap(), b)).exists() { if Path::new(&format!(
"{}/.cache/ame/{}",
env::var("HOME").unwrap(),
package
))
.exists()
{
if verbosity >= 1 { if verbosity >= 1 {
log("Old cache directory found, deleting".to_string()); log("Old cache directory found, deleting".to_string());
} }
fs::remove_dir_all(Path::new(&format!( fs::remove_dir_all(Path::new(&format!(
"{}/.cache/ame/{}", "{}/.cache/ame/{}",
env::var("HOME").unwrap(), env::var("HOME").unwrap(),
b package
))) )))
.unwrap(); .unwrap();
} }

@ -1,6 +1,6 @@
use runas::Command; use crate::error::SilentUnwrap;
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,10 +17,7 @@ pub fn upgrade(options: Options) {
log("Upgrading repo packages".to_string()); log("Upgrading repo packages".to_string());
} }
Command::new("pacman") sudo_pacman(pacman_args).silent_unwrap();
.args(&pacman_args)
.status()
.expect("Something has gone wrong");
if verbosity >= 1 { if verbosity >= 1 {
log("Upgrading AUR packages".to_string()); log("Upgrading AUR packages".to_string());

Loading…
Cancel
Save