From 3168e8f56015310e23f5fe76bd8ac4aa564c3d2f Mon Sep 17 00:00:00 2001 From: jnats Date: Fri, 24 Sep 2021 23:34:46 +0100 Subject: [PATCH] huge code audit --- Cargo.toml | 5 +- ame.toml | 9 --- src/main.rs | 155 +++++++++++------------------------------ src/mods.rs | 4 +- src/mods/clearcache.rs | 3 + src/mods/clone.rs | 78 +++++++++++++++------ src/mods/config.rs | 60 ---------------- src/mods/flatpak.rs | 11 --- src/mods/help.rs | 26 +++---- src/mods/install.rs | 16 +++-- src/mods/search.rs | 28 ++++++-- src/mods/strs.rs | 24 +++++++ src/mods/uninstall.rs | 19 ++--- src/mods/upgrade.rs | 67 ++++++++++++------ src/mods/ver.rs | 16 +++++ 15 files changed, 245 insertions(+), 276 deletions(-) delete mode 100644 ame.toml delete mode 100644 src/mods/config.rs delete mode 100644 src/mods/flatpak.rs create mode 100644 src/mods/strs.rs create mode 100644 src/mods/ver.rs diff --git a/Cargo.toml b/Cargo.toml index 8ea74d8..88bd916 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ame" -version = "2.0.0" +version = "3.0.0" authors = [ "jnats ", "axtlos " ] edition = "2018" description = "a fast and efficient aur helper." @@ -13,4 +13,5 @@ raur = "2.0.2" runas = "*" toml = "*" serde = "*" -walkdir = "*" \ No newline at end of file +walkdir = "*" +ansi_term = "*" diff --git a/ame.toml b/ame.toml deleted file mode 100644 index 9d31ea6..0000000 --- a/ame.toml +++ /dev/null @@ -1,9 +0,0 @@ -cache = "~/.cache/ame" - -[backends] -pacman = true -flatpak = false -aur = true - -[pacman] -noconfirm = false diff --git a/src/main.rs b/src/main.rs index e06e815..c2944b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,146 +1,73 @@ mod mods; -use toml; -use serde; -use mods::{clearcache::clearcache, clone::clone, help::help, install::install, search::{a_search, r_search}, uninstall::uninstall, upgrade::upgrade, flatpak::flatpak, config::printconfig}; -use std::{fs, fs::File, io::prelude::*, env, process::exit, process::Command}; - -// Code audit notes from axtlos: -/* Maybe we could change the code style for the if..elif..else structure so that it isnt -if { - -} elif { - -} - -but rather -if -{ - -} elif -{ - -} -So that the code is a bit more readable - -We should also check where we can "merge" variables or create new ones - -*/ -#[derive(serde::Deserialize)] -struct General { - cache: Option, - backends: Backends, - pacman: Pacman, -} - -#[derive(serde::Deserialize)] -struct Backends { - pacman: Option, - flatpak: Option, - aur: Option, -} - -#[derive(serde::Deserialize)] -struct Pacman { - noconfirm: Option, -} +use mods::{clearcache::clearcache, clone::clone, help::help, install::install, search::{a_search, r_search}, uninstall::uninstall, upgrade::upgrade, ver::ver}; +use std::{env, process::exit, process::Command}; fn main() { + // let statements let args: Vec = env::args().collect(); - let mut confile = File::open("/etc/ame.toml").expect("Unable to open the Config file, did you delete ame.toml from /etc/"); - let mut config = String::new(); - let defaultconfig = format!(r#" - cache = "{}/.cache/ame" - - [backends] - pacman = true - flatpak = true - aur = true - - [pacman] - noconfirm = false - "#, std::env::var("HOME").unwrap()); - let mut configfile: General = toml::from_str(&defaultconfig).unwrap(); - - if fs::read_to_string("/etc/ame.toml").expect("unable to open config file! (/etc/ame.toml)") != "" { //maybe print out a warning when the config file is empty so that the user knows the hardcoded one is being used - confile.read_to_string(&mut config).expect("Unable to read the Config file (/etc/ame.toml)"); - let homepath = std::env::var("HOME").unwrap(); - config=config.replace("~", &homepath); - configfile = toml::from_str(&config).unwrap(); - } + let homepath = std::env::var("HOME").unwrap(); + let cache_path = format!("/{}/.cache/ame/", homepath); + // args catch if args.len() <= 1 { help(); exit(1); } let oper = &args[1]; - let cache_path=configfile.cache.unwrap(); + + // install if oper == "-S" || oper == "ins" || oper == "install" { for arg in env::args().skip(2) { - if configfile.backends.pacman.unwrap() == true { - let out = Command::new("pacman").arg("-Ss").arg(&arg).status().unwrap(); // How do we silence this command?? using > /dev/null seems to also silence the returncode which is needed here - if out.success() { - let configoption_noconfirm = configfile.pacman.noconfirm.unwrap(); - install(configoption_noconfirm, &arg); - } else { - if configfile.backends.aur.unwrap() == true { - clone(&arg, &cache_path); - } else { - println!("ERROR: the package wasn't found in the repos and aur support is disabled"); - println!("Please enable aur support if you wish to check if this package exists in the aur"); - exit(1); - } - } - } else if configfile.backends.aur.unwrap() == true { - clone(&arg, &cache_path) + let out = Command::new("pacman") + .arg("-Ss") + .arg(&arg) + .arg(" > /dev/null && return ${PIPESTATUS}") + .status() + .unwrap(); + if out.success() { + install(&arg); } else { - println!("ERROR: it seems like neither pacman, nor aur support is enabled!"); - println!("Please enable either one of those option and try again"); - exit(1); + clone(&arg); } - } - } else if oper == "-R" || oper=="rem" || oper=="remove" { + } + + // remove + } else if oper == "-R" || oper == "-Rs" || oper=="rem" || oper=="remove" { for arg in env::args().skip(2) { - let configoption_noconfirm = configfile.pacman.noconfirm.unwrap(); - uninstall(configoption_noconfirm, &arg); + uninstall(&arg); } + + // upgrade } else if oper == "-Syu" || oper=="upg" || oper=="upgrade" { - let configoption_noconfirm = configfile.pacman.noconfirm.unwrap(); - upgrade(configoption_noconfirm, &cache_path); - } else if oper == "-Ss" || oper=="sear" || oper=="search" { + upgrade(&cache_path); + } else if oper == "-Ss" || oper=="sea" || oper=="search" { for arg in env::args().skip(2) { r_search(&arg); a_search(&arg); } - } else if oper == "-Sa" || oper=="sera" || oper=="search-aur" { + + // aur search + } else if oper == "-Sa" || oper=="aursea" || oper=="aursearch" { for arg in env::args().skip(2) { a_search(&arg); } - } else if oper == "-Sr" || oper=="serr" || oper=="search-rep" { + + // repo search + } else if oper == "-Sr" || oper=="repsea" || oper=="reposearch" { for arg in env::args().skip(2) { r_search(&arg); } - } else if oper == "-Cc" || oper=="clrca" || oper=="clear-cache" { + + // clear cache + } else if oper == "-Cc" || oper=="clr" || oper=="clear-cache" { clearcache(); - } else if oper == "-f" || oper=="flat" || oper=="flatpak" { - if configfile.backends.flatpak.unwrap() == true { - let b = std::path::Path::new("/usr/bin/flatpak").exists(); - if b == true { - for arg in env::args().skip(2) { - flatpak(&arg); - } - } else { - println!("ERROR: flatpak not found, please install flatpak and try again!"); - println!("If you do have flatpak installed, please open an issue on the ame github repo!"); - exit(1); - } - } else { - println!("ERROR: flatpak support is disabled in your ame config!"); - println!("Enable flatpak support in your configuration and try again!"); - exit(1); - } - } else if oper == "-Pc" || oper=="pricon" || oper=="printconf" { - printconfig(); + + // version / contrib + } else if oper == "-v" || oper == "-V" || oper == "ver" { + ver(); + + // help } else { help(); exit(0); diff --git a/src/mods.rs b/src/mods.rs index 2a86b45..ce3e1a1 100644 --- a/src/mods.rs +++ b/src/mods.rs @@ -5,5 +5,5 @@ pub mod install; pub mod search; pub mod uninstall; pub mod upgrade; -pub mod flatpak; -pub mod config; \ No newline at end of file +pub mod strs; +pub mod ver; diff --git a/src/mods/clearcache.rs b/src/mods/clearcache.rs index 7fca292..43f4b5e 100644 --- a/src/mods/clearcache.rs +++ b/src/mods/clearcache.rs @@ -1,8 +1,11 @@ use std::fs; +use crate::mods::strs::inf; pub fn clearcache() { let path = format!("{}/.cache/ame/", std::env::var("HOME").unwrap()); + inf(format!("Clearing cache")); + fs::remove_dir_all(&path).unwrap(); fs::create_dir(&path).unwrap(); } diff --git a/src/mods/clone.rs b/src/mods/clone.rs index 06dbdf6..dda1641 100644 --- a/src/mods/clone.rs +++ b/src/mods/clone.rs @@ -1,30 +1,66 @@ use git2::Repository; use std::{env, fs, path::Path, process::Command}; +use crate::mods::strs::{err_unrec, inf}; -// Code audit notes from axtlos: -/* - try to resolve the warning because of unused std::result::Result, no idea how to do that -*/ - -pub fn clone(pkg: &str, cachedir: &str) { - let error = format!("Couldn't install {}", &pkg); +pub fn clone(pkg: &str) { + let cachedir = format!("{}/.cache/ame", std::env::var("HOME").unwrap()); let path = Path::new(&cachedir); - let pkgdir=format!("{}/{}", &cachedir, &pkg); + let pkgdir = format!("{}/{}", &cachedir, &pkg); let pkgpath = Path::new(&pkgdir); + let results = raur::search(&pkg).expect("a"); + let url = format!("https://aur.archlinux.org/{}.git", results[0].name); + if !path.is_dir() { - fs::create_dir(&path); + let cache_result = fs::create_dir(&path); + match cache_result { + Ok(_) => { + inf(format!("Created cache path (first run)")) + } + Err(_) => { + err_unrec(format!("Could not create cache path")) + }} } - env::set_current_dir(&pkgdir); - fs::create_dir(&pkg); - let results = raur::search(&pkg).expect(&error); - let url = format!("https://aur.archlinux.org/{}.git", results[0].name); - println!("Cloning {} ...", pkg); - println!("{}", &cachedir); + + inf(format!("Cloning {} ...", pkg)); + + let cd_result = env::set_current_dir(&pkgdir); + match cd_result { + Ok(_) => { + inf(format!("Entered cache directory")) + } + Err(_) => { + err_unrec(format!("")) + }} + + let dir_result = fs::create_dir(&pkg); + match dir_result { + Ok(_) => { + inf(format!("Cloned {} to package directory", pkg)) + } + Err(_) => { + err_unrec(format!("Couldn't create package directory for {}", pkg)) + }} + Repository::clone(&url, &pkgpath).unwrap(); - env::set_current_dir(&pkgpath); - println!("Installing {} ...", pkg); - Command::new("makepkg") - .arg("-si") - .status() - .expect(&error); + + let cd2_result = env::set_current_dir(&pkgpath); + match cd2_result { + Ok(_) => { + inf(format!("Entering package directory for {}", pkg)) + } + Err(_) => { + err_unrec(format!("Couldn't enter cache directory for {}", pkg)) + }} + + inf(format!("Installing {} ...", pkg)); + let install_result = Command::new("makepkg") + .arg("-si") + .status(); + match install_result { + Ok(_) => { + inf(format!("Succesfully installed {}", pkg)); + } + Err(_) => { + err_unrec(format!("Couldn't install {}", pkg)); + }}; } diff --git a/src/mods/config.rs b/src/mods/config.rs deleted file mode 100644 index cbd6f3e..0000000 --- a/src/mods/config.rs +++ /dev/null @@ -1,60 +0,0 @@ -use toml; -use serde; -use std::{fs, fs::File, io::prelude::*}; - - -#[derive(serde::Deserialize)] -struct General { - cache: Option, - backends: Backends, - pacman: Pacman, -} - -#[derive(serde::Deserialize)] -struct Backends { - pacman: Option, - flatpak: Option, - aur: Option, -} - -#[derive(serde::Deserialize)] -struct Pacman { - noconfirm: Option, -} - - - -pub fn printconfig() { - let mut confile = File::open("/etc/ame.toml").expect("Unable to open the Config file, did you delete ame.toml from /etc/??"); - let mut config = String::new(); - let defaultconfig = format!(r#" - cache = "{}/.cache/ame" - - [backends] - pacman = true - flatpak = true - aur = true - - [pacman] - noconfirm = false - "#, std::env::var("HOME").unwrap()); - let mut configfile: General = toml::from_str(&defaultconfig).unwrap(); - if fs::read_to_string("/etc/ame.toml").expect("unable to open config file! (/etc/ame.toml)") != "" { //maybe print out a warning when the config file is empty so that the user knows the hardcoded one is being used - confile.read_to_string(&mut config).expect("Unable to read the Config file (/etc/ame.toml)"); - let homepath = std::env::var("HOME").unwrap(); - config=config.replace("~", &homepath); - configfile = toml::from_str(&config).unwrap(); - } - println!("\ -General: - Cache directory: {} - -Backends: - pacman support: {} - aur support: {} - flatpak support: {} - -Pacman: - noconfirm: {} -", configfile.cache.unwrap(), configfile.backends.pacman.unwrap(), configfile.backends.aur.unwrap(), configfile.backends.flatpak.unwrap(), configfile.pacman.noconfirm.unwrap()); -} \ No newline at end of file diff --git a/src/mods/flatpak.rs b/src/mods/flatpak.rs deleted file mode 100644 index 251cbf2..0000000 --- a/src/mods/flatpak.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::process::Command; - - -pub fn flatpak(pkg:&str) { - let error = format!("Couldn't install {}", &pkg); - Command::new("flatpak") - .arg("install") - .arg(&pkg) - .status() - .expect(&error); -} \ No newline at end of file diff --git a/src/mods/help.rs b/src/mods/help.rs index 2d7a181..d2a2d1f 100644 --- a/src/mods/help.rs +++ b/src/mods/help.rs @@ -1,13 +1,15 @@ +use crate::mods::strs::inf; + pub fn help() { // work on a proper error message, the python ame one isnt really better in my opinion - println!("\ -Usage:\n -ame -S - install a package -ame -f - install a package via flatpak -ame -s - install a package via snap -ame -R - remove a package -ame -Syu - system upgrade -ame -Ss - search for a package -ame -Sa - search for a package over the aur -ame -Sr - search for a package over the repos -ame -Cc - clear package cache") -} \ No newline at end of file + inf(format!("Usage:")); + println!(" +ame -S / -Sy / ins - install a package +ame -R / -Rs / rem - remove a package +ame -Syu / upg - upgrade all packages to latest version +ame -Ss / sea - search for a package +ame -Sa / aursea - search for a package in the aur +ame -Sr / repsea - search for a package in the repos +ame -v / -V / ver - contributors and version info +" +); +} diff --git a/src/mods/install.rs b/src/mods/install.rs index d68b946..f0cb5bb 100644 --- a/src/mods/install.rs +++ b/src/mods/install.rs @@ -1,11 +1,13 @@ use runas::Command; +use crate::mods::strs::{inf, err_unrec}; -pub fn install(noconfirm: bool, pkg: &str) { - println!("{}",noconfirm); - let errstr = format!("Oops.. Something went wrong!"); // we should make one set way of how error messages are written - if noconfirm == false { - Command::new("pacman").arg("-S").arg(&pkg).status().expect(&errstr); - } else { - Command::new("pacman").arg("-S").arg("--noconfirm").arg(&pkg).status().expect(&errstr); +pub fn install(pkg: &str) { + let result = Command::new("pacman").arg("-Sy").arg(&pkg).status(); + match result { + Ok(_) => { + inf(format!("Succesfully installed {}", pkg)) } + Err(_) => { + err_unrec(format!("Couldn't install {}", pkg)) + }}; } diff --git a/src/mods/search.rs b/src/mods/search.rs index 6457eb7..b9b4cf9 100644 --- a/src/mods/search.rs +++ b/src/mods/search.rs @@ -1,17 +1,31 @@ use std::{ops::Deref, process::Command}; +use crate::mods::strs::{err_unrec, inf}; pub fn a_search(pkg: &str) { let results = raur::search(&pkg); + for res in &results { - println!("aur/{} {}\n {}", res[0].name, res[0].version, res[0].description.as_ref().map_or("n/a", String::deref)); //i like your funny words, magic man (seriously, what does this do??) + if res.len() <= 1 { + err_unrec(format!("No matching packages found")); + } + println!("aur/{} {}\n {}", + res[0].name, + res[0].version, + res[0].description.as_ref().map_or("n/a", String::deref)); } } pub fn r_search(pkg: &str) { - let errstr = format!("Something happened"); - Command::new("pacman") - .arg("-Ss") - .arg(&pkg) - .status() - .expect(&errstr); + let result = Command::new("pacman") + .arg("-Ss") + .arg(&pkg) + .status(); + match result { + Ok(_) => { + inf(format!("Repo search successful")) + } + Err(_) => { + err_unrec(format!("Couldn't search pacman repos")) + }}; + } diff --git a/src/mods/strs.rs b/src/mods/strs.rs new file mode 100644 index 0000000..45eb83e --- /dev/null +++ b/src/mods/strs.rs @@ -0,0 +1,24 @@ +use ansi_term::Colour; +use std::process; + +pub fn inf(a: std::string::String){ + println!("{} {}", + Colour::Purple.bold().paint("❖"), + Colour::White.paint(a)); +} + +pub fn err_unrec(a: std::string::String) { + println!("{} {} {}", + Colour::Red.bold().paint("✖ Unrecoverable error:"), + Colour::Red.paint(a), + Colour::Red.bold().paint("Terminating.")); + process::exit(1); +} + +// we havent actually used this one yet + +/*pub fn err_rec(a: std::string::String) { + println!("{} {}", + Colour::Yellow.bold().paint("! Warning:"), + Colour::Yellow.paint(a)); +}*/ diff --git a/src/mods/uninstall.rs b/src/mods/uninstall.rs index dacad55..a420255 100644 --- a/src/mods/uninstall.rs +++ b/src/mods/uninstall.rs @@ -1,11 +1,14 @@ use runas::Command; +use crate::mods::strs::{inf, err_unrec}; -pub fn uninstall(noconfirm: bool, pkg: &str) { - let errstr = format!("Could not remove package {}", pkg); //again, we should choose one way to do error messages - - if noconfirm == false { - Command::new("pacman").arg("-R").arg(&pkg).status().expect(&errstr); - } else { - Command::new("pacman").arg("-R").arg("--noconfirm").arg(&pkg).status().expect(&errstr); - } +pub fn uninstall(pkg: &str) { + inf(format!("Attempting to uninstall {}", pkg)); + let result = Command::new("pacman").arg("-Rs").arg(&pkg).status(); + match result { + Ok(_) => { + println!("") + } + Err(_) => { + err_unrec(format!("Couldn't uninstall {}", pkg)) + }}; } diff --git a/src/mods/upgrade.rs b/src/mods/upgrade.rs index 49b3a3b..67709c0 100644 --- a/src/mods/upgrade.rs +++ b/src/mods/upgrade.rs @@ -1,35 +1,56 @@ use runas::Command; -use git2::Repository; -use std::{path, env}; +use std::env; +use crate::mods::strs::{err_unrec, inf}; -// fix unused std::result::Result - -pub fn upgrade(noconfirm: bool, cachedir: &str){ - let errstr = format!("Something happened"); - if noconfirm == true { - Command::new("pacman") - .arg("-Syu") - .arg("--noconfirm") - .status() - .expect(&errstr); - } else { - Command::new("pacman") - .arg("-Syu") - .status() - .expect(&errstr); +pub fn upgrade(cachedir: &str){ + let result = Command::new("pacman") + .arg("-Syu") + .status(); + match result { + Ok(_) => { + inf(format!("All repo packages upgraded")) } + Err(_) => { + err_unrec(format!("Couldn't upgrade packages")) + }}; + for file in std::fs::read_dir(&cachedir).unwrap() { let dir = &file.unwrap().path(); - env::set_current_dir(&dir); - let output = std::process::Command::new("git").arg("pull").output().unwrap(); //figure out how to pull with the git2 crate! + let output = std::process::Command::new("git").arg("pull").output().unwrap(); let update_available = String::from_utf8(output.stdout).unwrap(); + + let cd_result = env::set_current_dir(&dir); + match cd_result { + Ok(_) => { + inf(format!("Entered AUR package directory to pull changes")) + } + Err(_) => { + err_unrec(format!("Could not enter AUR package directory to pull changes")) + }} + if update_available != "Already up to date." { let path_as_str = &dir.display().to_string(); let pkg: Vec<&str> = path_as_str.split("/").collect(); - println!("{} is up to date", pkg[pkg.len()-1]); + + inf(format!("{} is up to date", pkg[pkg.len()-1])); } else { - env::set_current_dir(&dir); - std::process::Command::new("makepkg").arg("-si").status(); + let cd2_result = env::set_current_dir(&dir); + match cd2_result { + Ok(_) => { + inf(format!("Entering AUR package directory to install new version")) + } + Err(_) => { + err_unrec(format!("Couldn't enter AUR package directory to install new version")) + }} + + let makepkg_result = std::process::Command::new("makepkg").arg("-si").status(); + match makepkg_result { + Ok(_) => { + inf(format!("New AUR package version installed")) + } + Err(_) => { + err_unrec(format!("Couldn't install new AUR package version")) + }} } } -} +} diff --git a/src/mods/ver.rs b/src/mods/ver.rs new file mode 100644 index 0000000..00df516 --- /dev/null +++ b/src/mods/ver.rs @@ -0,0 +1,16 @@ +use crate::mods::strs::inf; + +pub fn ver() { + inf(format!("ame - v3.0.0")); + println!(""); + inf(format!("Contributors:")); + println!("- axtlos "); + println!("- jnats "); + println!("- jasio "); + println!("- generic "); + println!(""); + inf(format!("This software is licensed under the BSD 3-Clause license.")); + inf(format!("All source code is available at:")); + println!("https://github.com/crystal-linux/ame"); + println!(""); +}