huge code audit

i18n
jnats 3 years ago
parent fb7995d9db
commit 3168e8f560

@ -1,6 +1,6 @@
[package] [package]
name = "ame" name = "ame"
version = "2.0.0" version = "3.0.0"
authors = [ "jnats <jnats@salyut.one>", "axtlos <axtlos@salyut.one>" ] authors = [ "jnats <jnats@salyut.one>", "axtlos <axtlos@salyut.one>" ]
edition = "2018" edition = "2018"
description = "a fast and efficient aur helper." description = "a fast and efficient aur helper."
@ -13,4 +13,5 @@ raur = "2.0.2"
runas = "*" runas = "*"
toml = "*" toml = "*"
serde = "*" serde = "*"
walkdir = "*" walkdir = "*"
ansi_term = "*"

@ -1,9 +0,0 @@
cache = "~/.cache/ame"
[backends]
pacman = true
flatpak = false
aur = true
[pacman]
noconfirm = false

@ -1,146 +1,73 @@
mod mods; mod mods;
use toml; use mods::{clearcache::clearcache, clone::clone, help::help, install::install, search::{a_search, r_search}, uninstall::uninstall, upgrade::upgrade, ver::ver};
use serde; use std::{env, process::exit, process::Command};
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 <condition> {
} elif <condition> {
}
but rather
if <condition>
{
} elif <condition>
{
}
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<String>,
backends: Backends,
pacman: Pacman,
}
#[derive(serde::Deserialize)]
struct Backends {
pacman: Option<bool>,
flatpak: Option<bool>,
aur: Option<bool>,
}
#[derive(serde::Deserialize)]
struct Pacman {
noconfirm: Option<bool>,
}
fn main() { fn main() {
// let statements
let args: Vec<String> = env::args().collect(); let args: Vec<String> = 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 homepath = std::env::var("HOME").unwrap();
let mut config = String::new(); let cache_path = format!("/{}/.cache/ame/", homepath);
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();
}
// args catch
if args.len() <= 1 { if args.len() <= 1 {
help(); help();
exit(1); exit(1);
} }
let oper = &args[1]; let oper = &args[1];
let cache_path=configfile.cache.unwrap();
// install
if oper == "-S" || oper == "ins" || oper == "install" { if oper == "-S" || oper == "ins" || oper == "install" {
for arg in env::args().skip(2) { for arg in env::args().skip(2) {
if configfile.backends.pacman.unwrap() == true { let out = Command::new("pacman")
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 .arg("-Ss")
if out.success() { .arg(&arg)
let configoption_noconfirm = configfile.pacman.noconfirm.unwrap(); .arg(" > /dev/null && return ${PIPESTATUS}")
install(configoption_noconfirm, &arg); .status()
} else { .unwrap();
if configfile.backends.aur.unwrap() == true { if out.success() {
clone(&arg, &cache_path); install(&arg);
} 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)
} else { } else {
println!("ERROR: it seems like neither pacman, nor aur support is enabled!"); clone(&arg);
println!("Please enable either one of those option and try again");
exit(1);
} }
} }
} 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) { for arg in env::args().skip(2) {
let configoption_noconfirm = configfile.pacman.noconfirm.unwrap(); uninstall(&arg);
uninstall(configoption_noconfirm, &arg);
} }
// upgrade
} else if oper == "-Syu" || oper=="upg" || oper=="upgrade" { } else if oper == "-Syu" || oper=="upg" || oper=="upgrade" {
let configoption_noconfirm = configfile.pacman.noconfirm.unwrap(); upgrade(&cache_path);
upgrade(configoption_noconfirm, &cache_path); } else if oper == "-Ss" || oper=="sea" || oper=="search" {
} else if oper == "-Ss" || oper=="sear" || oper=="search" {
for arg in env::args().skip(2) { for arg in env::args().skip(2) {
r_search(&arg); r_search(&arg);
a_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) { for arg in env::args().skip(2) {
a_search(&arg); 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) { for arg in env::args().skip(2) {
r_search(&arg); r_search(&arg);
} }
} else if oper == "-Cc" || oper=="clrca" || oper=="clear-cache" {
// clear cache
} else if oper == "-Cc" || oper=="clr" || oper=="clear-cache" {
clearcache(); clearcache();
} else if oper == "-f" || oper=="flat" || oper=="flatpak" {
if configfile.backends.flatpak.unwrap() == true { // version / contrib
let b = std::path::Path::new("/usr/bin/flatpak").exists(); } else if oper == "-v" || oper == "-V" || oper == "ver" {
if b == true { ver();
for arg in env::args().skip(2) {
flatpak(&arg); // help
}
} 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();
} else { } else {
help(); help();
exit(0); exit(0);

@ -5,5 +5,5 @@ pub mod install;
pub mod search; pub mod search;
pub mod uninstall; pub mod uninstall;
pub mod upgrade; pub mod upgrade;
pub mod flatpak; pub mod strs;
pub mod config; pub mod ver;

@ -1,8 +1,11 @@
use std::fs; use std::fs;
use crate::mods::strs::inf;
pub fn clearcache() { pub fn clearcache() {
let path = format!("{}/.cache/ame/", std::env::var("HOME").unwrap()); let path = format!("{}/.cache/ame/", std::env::var("HOME").unwrap());
inf(format!("Clearing cache"));
fs::remove_dir_all(&path).unwrap(); fs::remove_dir_all(&path).unwrap();
fs::create_dir(&path).unwrap(); fs::create_dir(&path).unwrap();
} }

@ -1,30 +1,66 @@
use git2::Repository; use git2::Repository;
use std::{env, fs, path::Path, process::Command}; use std::{env, fs, path::Path, process::Command};
use crate::mods::strs::{err_unrec, inf};
// Code audit notes from axtlos: pub fn clone(pkg: &str) {
/* let cachedir = format!("{}/.cache/ame", std::env::var("HOME").unwrap());
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);
let path = Path::new(&cachedir); let path = Path::new(&cachedir);
let pkgdir=format!("{}/{}", &cachedir, &pkg); let pkgdir = format!("{}/{}", &cachedir, &pkg);
let pkgpath = Path::new(&pkgdir); 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() { 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); inf(format!("Cloning {} ...", pkg));
let results = raur::search(&pkg).expect(&error);
let url = format!("https://aur.archlinux.org/{}.git", results[0].name); let cd_result = env::set_current_dir(&pkgdir);
println!("Cloning {} ...", pkg); match cd_result {
println!("{}", &cachedir); 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(); Repository::clone(&url, &pkgpath).unwrap();
env::set_current_dir(&pkgpath);
println!("Installing {} ...", pkg); let cd2_result = env::set_current_dir(&pkgpath);
Command::new("makepkg") match cd2_result {
.arg("-si") Ok(_) => {
.status() inf(format!("Entering package directory for {}", pkg))
.expect(&error); }
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));
}};
} }

@ -1,60 +0,0 @@
use toml;
use serde;
use std::{fs, fs::File, io::prelude::*};
#[derive(serde::Deserialize)]
struct General {
cache: Option<String>,
backends: Backends,
pacman: Pacman,
}
#[derive(serde::Deserialize)]
struct Backends {
pacman: Option<bool>,
flatpak: Option<bool>,
aur: Option<bool>,
}
#[derive(serde::Deserialize)]
struct Pacman {
noconfirm: Option<bool>,
}
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());
}

@ -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);
}

@ -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 pub fn help() { // work on a proper error message, the python ame one isnt really better in my opinion
println!("\ inf(format!("Usage:"));
Usage:\n println!("
ame -S <pkg> - install a package ame -S / -Sy / ins <pkg> - install a package
ame -f <pkg> - install a package via flatpak ame -R / -Rs / rem <pkg> - remove a package
ame -s <pkg> - install a package via snap ame -Syu / upg - upgrade all packages to latest version
ame -R <pkg> - remove a package ame -Ss / sea <pkg> - search for a package
ame -Syu - system upgrade ame -Sa / aursea <pkg> - search for a package in the aur
ame -Ss <pkg> - search for a package ame -Sr / repsea <pkg> - search for a package in the repos
ame -Sa <pkg> - search for a package over the aur ame -v / -V / ver - contributors and version info
ame -Sr <pkg> - search for a package over the repos "
ame -Cc - clear package cache") );
} }

@ -1,11 +1,13 @@
use runas::Command; use runas::Command;
use crate::mods::strs::{inf, err_unrec};
pub fn install(noconfirm: bool, pkg: &str) { pub fn install(pkg: &str) {
println!("{}",noconfirm); let result = Command::new("pacman").arg("-Sy").arg(&pkg).status();
let errstr = format!("Oops.. Something went wrong!"); // we should make one set way of how error messages are written match result {
if noconfirm == false { Ok(_) => {
Command::new("pacman").arg("-S").arg(&pkg).status().expect(&errstr); inf(format!("Succesfully installed {}", pkg))
} else {
Command::new("pacman").arg("-S").arg("--noconfirm").arg(&pkg).status().expect(&errstr);
} }
Err(_) => {
err_unrec(format!("Couldn't install {}", pkg))
}};
} }

@ -1,17 +1,31 @@
use std::{ops::Deref, process::Command}; use std::{ops::Deref, process::Command};
use crate::mods::strs::{err_unrec, inf};
pub fn a_search(pkg: &str) { pub fn a_search(pkg: &str) {
let results = raur::search(&pkg); let results = raur::search(&pkg);
for res in &results { 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) { pub fn r_search(pkg: &str) {
let errstr = format!("Something happened"); let result = Command::new("pacman")
Command::new("pacman") .arg("-Ss")
.arg("-Ss") .arg(&pkg)
.arg(&pkg) .status();
.status() match result {
.expect(&errstr); Ok(_) => {
inf(format!("Repo search successful"))
}
Err(_) => {
err_unrec(format!("Couldn't search pacman repos"))
}};
} }

@ -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));
}*/

@ -1,11 +1,14 @@
use runas::Command; use runas::Command;
use crate::mods::strs::{inf, err_unrec};
pub fn uninstall(noconfirm: bool, pkg: &str) { pub fn uninstall(pkg: &str) {
let errstr = format!("Could not remove package {}", pkg); //again, we should choose one way to do error messages inf(format!("Attempting to uninstall {}", pkg));
let result = Command::new("pacman").arg("-Rs").arg(&pkg).status();
if noconfirm == false { match result {
Command::new("pacman").arg("-R").arg(&pkg).status().expect(&errstr); Ok(_) => {
} else { println!("")
Command::new("pacman").arg("-R").arg("--noconfirm").arg(&pkg).status().expect(&errstr); }
} Err(_) => {
err_unrec(format!("Couldn't uninstall {}", pkg))
}};
} }

@ -1,35 +1,56 @@
use runas::Command; use runas::Command;
use git2::Repository; use std::env;
use std::{path, env}; use crate::mods::strs::{err_unrec, inf};
// fix unused std::result::Result pub fn upgrade(cachedir: &str){
let result = Command::new("pacman")
pub fn upgrade(noconfirm: bool, cachedir: &str){ .arg("-Syu")
let errstr = format!("Something happened"); .status();
if noconfirm == true { match result {
Command::new("pacman") Ok(_) => {
.arg("-Syu") inf(format!("All repo packages upgraded"))
.arg("--noconfirm")
.status()
.expect(&errstr);
} else {
Command::new("pacman")
.arg("-Syu")
.status()
.expect(&errstr);
} }
Err(_) => {
err_unrec(format!("Couldn't upgrade packages"))
}};
for file in std::fs::read_dir(&cachedir).unwrap() { for file in std::fs::read_dir(&cachedir).unwrap() {
let dir = &file.unwrap().path(); let dir = &file.unwrap().path();
env::set_current_dir(&dir); let output = std::process::Command::new("git").arg("pull").output().unwrap();
let output = std::process::Command::new("git").arg("pull").output().unwrap(); //figure out how to pull with the git2 crate!
let update_available = String::from_utf8(output.stdout).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." { if update_available != "Already up to date." {
let path_as_str = &dir.display().to_string(); let path_as_str = &dir.display().to_string();
let pkg: Vec<&str> = path_as_str.split("/").collect(); 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 { } else {
env::set_current_dir(&dir); let cd2_result = env::set_current_dir(&dir);
std::process::Command::new("makepkg").arg("-si").status(); 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"))
}}
} }
} }
} }

@ -0,0 +1,16 @@
use crate::mods::strs::inf;
pub fn ver() {
inf(format!("ame - v3.0.0"));
println!("");
inf(format!("Contributors:"));
println!("- axtlos <axtlos@salyut.one>");
println!("- jnats <jnats@salyut.one>");
println!("- jasio <jasiobene@icloud.com>");
println!("- generic <mdc028@bucknell.edu>");
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!("");
}
Loading…
Cancel
Save