huge code audit

i18n
jnats 3 years ago
parent fb7995d9db
commit 3168e8f560

@ -1,6 +1,6 @@
[package]
name = "ame"
version = "2.0.0"
version = "3.0.0"
authors = [ "jnats <jnats@salyut.one>", "axtlos <axtlos@salyut.one>" ]
edition = "2018"
description = "a fast and efficient aur helper."
@ -13,4 +13,5 @@ raur = "2.0.2"
runas = "*"
toml = "*"
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;
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 <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>,
}
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<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 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);

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

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

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

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

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

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

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

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

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