From d2e377f7f936d068253913a7e23da7636cf2fe81 Mon Sep 17 00:00:00 2001 From: michal Date: Sat, 4 Dec 2021 19:18:07 +0000 Subject: [PATCH] replaced raur + general linting and checking --- Cargo.toml | 22 ++++++++----------- src/main.rs | 9 ++++++-- src/mods.rs | 3 ++- src/mods/clone.rs | 40 +++++++++++++++++----------------- src/mods/database.rs | 20 ++++++++++------- src/mods/rpc.rs | 39 +++++++++++++++++++++++++++++++++ src/mods/search.rs | 26 +++++++++++----------- src/mods/stat_database.rs | 45 +++++++++------------------------------ src/mods/statpkgs.rs | 33 +++++++++++++++------------- src/mods/uninstall.rs | 37 ++++++++++++++++++++++++++++++++ src/mods/upgrade.rs | 17 +++++++-------- src/mods/ver.rs | 6 ++++-- 12 files changed, 181 insertions(+), 116 deletions(-) create mode 100644 src/mods/rpc.rs diff --git a/Cargo.toml b/Cargo.toml index 70e2c70..05ef45f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,16 +8,12 @@ description = "a fast and efficient aur helper." # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -raur = "3.0.1" -runas = "*" -ansi_term = "*" -uwuizer = "*" -moins = "*" -regex = "*" -toml_edit = "*" -toml = "*" -bytes = "*" -nix = "*" -clap = "*" -sqlite = "*" -file_diff = "*" +runas = "0.2.1" +ansi_term = "0.12.1" +uwuizer = "0.2.1" +moins = "0.5.0" +regex = { version = "1.5.4", default-features = false } +toml = "0.5.8" +sqlite = "0.26.0" +reqwest = { version = "0.11.7", default-features = false, features = [ "blocking", "json", "default-tls" ] } +serde = { version = "1.0.90", default-features = false, features = [ "derive" ] } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6050c3c..a88ddcc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ mod mods; use mods::{ clearcache::clearcache, clone::clone, - database::{add_pkg, create_database}, + database::create_database, help::help, inssort::{inssort, inssort_from_file}, install::install, @@ -22,7 +22,12 @@ use mods::{ use std::{env, process::exit}; fn main() { - if nix::unistd::Uid::effective().is_root() { + + extern "C" { + fn geteuid() -> u32; + } + + if unsafe { geteuid() } == 0 { // check if user runs ame as root err_unrec( "Do not run ame as root! this can cause serious damage to your system!".to_string(), diff --git a/src/mods.rs b/src/mods.rs index 0eb14d1..932c8db 100644 --- a/src/mods.rs +++ b/src/mods.rs @@ -13,4 +13,5 @@ pub mod uninstall; pub mod update; pub mod upgrade; pub mod ver; -pub mod xargs; \ No newline at end of file +pub mod xargs; +pub mod rpc; \ No newline at end of file diff --git a/src/mods/clone.rs b/src/mods/clone.rs index fee6a8b..b0fe586 100644 --- a/src/mods/clone.rs +++ b/src/mods/clone.rs @@ -1,13 +1,16 @@ use crate::{ - err_unrec, inf, inssort, mods::database::add_pkg, mods::purge::purge, mods::strs::prompt, - mods::strs::sec, mods::strs::succ, + err_unrec, inf, mods::database::add_pkg, mods::purge::purge, mods::strs::prompt, + mods::strs::sec, mods::strs::succ, mods::rpc::* }; use moins::Moins; use std::{env, fs, path::Path, process::Command}; fn uninstall_make_depend(pkg: &str) { // uninstall make depends of a package - let make_depends = raur::info(&[&pkg]).unwrap()[0].make_depends.clone(); + + // gets the "make_depends" field of the package using rpcinfo() + // let make_depends = rpcinfo(pkg)[0].make_depends; + let make_depends = rpcinfo(pkg).make_depends; let explicit_packages = Command::new("pacman") .arg("-Qetq") @@ -18,13 +21,12 @@ fn uninstall_make_depend(pkg: &str) { let expl_pkgs_parse = String::from_utf8(explicit_packages.stdout).unwrap(); let expl_pkgs_parse = expl_pkgs_parse.split('\n').collect::>(); - let mut rem_pkgs = Vec::new(); + let mut rem_pkgs: Vec = Vec::new(); for pkg in expl_pkgs_parse { - #[allow(clippy::needless_range_loop)] - for i in 0..make_depends.len() { - if let false = make_depends[i].contains(pkg) { - if let false = rem_pkgs.contains(&make_depends[i]) { - rem_pkgs.push(make_depends[i].as_str().to_string()); + for md in &make_depends { + if let false = md.contains(pkg) { + if let false = rem_pkgs.contains(md) { + rem_pkgs.push(md.as_str().to_string()); } }; } @@ -49,14 +51,17 @@ pub fn clone(noconfirm: bool, as_dep: bool, pkg: &str) { let cachedir = format!("{}/.cache/ame", env::var("HOME").unwrap()); let path = Path::new(&cachedir); let pkgdir = format!("{}/{}", &cachedir, &pkg); - let package = raur::info(&[pkg]).unwrap(); - - if package.is_empty() { + let search = rpcsearch(pkg).results; + if search.is_empty() { err_unrec("No matching AUR packages found".to_string()); } let url = format!("https://aur.archlinux.org/{}.git", pkg); + if !Path::new(&format!("{}/.cache", env::var("HOME").unwrap())).exists() { + fs::create_dir_all(format!("{}/.cache", env::var("HOME").unwrap())) + .expect("Failed to create ~/.cache directory"); + } if !path.is_dir() { let cache_result = fs::create_dir(&path); match cache_result { @@ -95,7 +100,7 @@ pub fn clone(noconfirm: bool, as_dep: bool, pkg: &str) { sec("Installing AUR package depends".to_string()); - inssort(noconfirm, true, package[0].depends.clone()); + // inssort(noconfirm, true, package[0].depends.clone()); let clone = std::process::Command::new("git") .arg("clone") @@ -130,8 +135,7 @@ pub fn clone(noconfirm: bool, as_dep: bool, pkg: &str) { match install_result { Ok(_) => { uninstall_make_depend(pkg); - let mut vec = Vec::new(); - vec.push(pkg); + let vec = vec![pkg]; add_pkg(false, &vec); } Err(_) => { @@ -147,8 +151,7 @@ pub fn clone(noconfirm: bool, as_dep: bool, pkg: &str) { match install_result.code() { Some(0) => { uninstall_make_depend(pkg); - let mut vec = Vec::new(); - vec.push(pkg); + let vec = vec![pkg]; add_pkg(false, &vec); } Some(_) => { @@ -170,8 +173,7 @@ pub fn clone(noconfirm: bool, as_dep: bool, pkg: &str) { match install_result { Ok(_) => { uninstall_make_depend(pkg); - let mut vec = Vec::new(); - vec.push(pkg); + let vec = vec![pkg]; add_pkg(false, &vec); } Err(_) => { diff --git a/src/mods/database.rs b/src/mods/database.rs index afa2fdb..2b576a0 100644 --- a/src/mods/database.rs +++ b/src/mods/database.rs @@ -1,9 +1,13 @@ -use crate::{err_unrec, inf}; +use crate::{err_unrec, inf, mods::rpc::*}; use std::{env, fs}; pub fn create_database() { let homepath = env::var("HOME").unwrap(); let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); + if !std::path::Path::new(&format!("{}/.local", env::var("HOME").unwrap())).exists() { + fs::create_dir_all(format!("{}/.local", env::var("HOME").unwrap())) + .expect("Failed to create ~/.local"); + } if !std::path::Path::new(&format!("{}/.local/share/ame/", env::var("HOME").unwrap())).is_dir() { let _cdar = fs::create_dir_all(format!("/{}/.local/ame/", homepath)); match _cdar { @@ -11,7 +15,7 @@ pub fn create_database() { inf("Created path for database (previously missing)".to_string()); } Err(_) => { - err_unrec("Couldn't create path for database (~/.local/rhare/ame)".to_string()) + err_unrec("Couldn't create path for database (~/.local/share/ame)".to_string()) } } } @@ -85,18 +89,18 @@ pub fn rem_pkg(pkgs: &[String]) { } } -pub fn add_pkg(from_repo: bool, pkgs: &Vec<&str>) { +pub fn add_pkg(from_repo: bool, pkgs: &[&str]) { for pkg in pkgs { let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); let connection = sqlite::open(file).unwrap(); - let results = raur::search(&pkg); + let results = rpcsearch(pkg).results; let mut package_name = String::new(); let mut package_version = String::new(); for res in &results { - package_name = res[0].name.to_string(); - package_version = res[0].version.to_string(); + package_name = res.name.clone(); + package_version = res.version.clone(); } - if from_repo == false { + if !from_repo { let result = connection.execute(format!( " INSERT INTO pkgs (name, version) VALUES (\"{}\", \"{}\"); @@ -112,7 +116,7 @@ pub fn add_pkg(from_repo: bool, pkgs: &Vec<&str>) { " INSERT INTO pkgs (name, version) VALUES (\"{}\", \"{}\"); ", - pkg, "from_repo".to_string() + pkg, "from_repo" )); match result { Ok(_) => inf(format!("Added {} to database", package_name)), diff --git a/src/mods/rpc.rs b/src/mods/rpc.rs new file mode 100644 index 0000000..5d6d9d7 --- /dev/null +++ b/src/mods/rpc.rs @@ -0,0 +1,39 @@ +#[derive(serde::Deserialize, Debug)] +pub struct Package { + #[serde(rename = "Name")] + pub name: String, + #[serde(rename = "Version")] + pub version: String, + #[serde(rename = "Description")] + pub description: Option, + #[serde(default)] + #[serde(rename = "Depends")] + pub depends: Vec, + #[serde(default)] + #[serde(rename = "MakeDepends")] + pub make_depends: Vec +} + +#[derive(serde::Deserialize)] +pub struct SearchResults { + pub resultcount: u32, + pub results: Vec +} + +pub fn rpcinfo(pkg: &str) -> Package { + let res = reqwest::blocking::get(&format!( + "https://aur.archlinux.org/rpc/?v=5&type=info&arg={}", + pkg + )).unwrap(); + + res.json().unwrap() +} + +pub fn rpcsearch(pkg: &str) -> SearchResults { + let res = reqwest::blocking::get(&format!( + "https://aur.archlinux.org/rpc/?v=5&type=search&arg={}", + pkg + )).unwrap(); + + res.json().unwrap() +} \ No newline at end of file diff --git a/src/mods/search.rs b/src/mods/search.rs index d92f93c..eedacbf 100644 --- a/src/mods/search.rs +++ b/src/mods/search.rs @@ -1,24 +1,26 @@ use crate::mods::strs::{err_rec, err_unrec, succ}; +use crate::mods::rpc::*; use ansi_term::Colour; -use std::{ops::Deref, process::Command}; +use std::process::Command; pub fn a_search(pkg: &str) { // search for a package in the AUR - let results = raur::search(&pkg); + let results = rpcsearch(pkg).results; for r in &results { - if r.is_empty() { + if results.is_empty() { err_rec("No matching AUR packages found".to_string()); } - for res in r { - println!( - "{}{} {}\n {}", - Colour::Cyan.bold().paint("aur/"), - Colour::White.bold().paint(&res.name), - Colour::Green.bold().paint(&res.version), - Colour::White.paint(res.description.as_ref().map_or("n/a", String::deref)) - ); - } + println!( + "{}{} {}\n {}", + Colour::Cyan.bold().paint("aur/"), + Colour::White.bold().paint(&r.name), + Colour::Green.bold().paint(&r.version), + Colour::White.paint(r.description.as_ref().unwrap_or(&"No description available".to_string())) + ); + } + if !results.is_empty() { + succ("AUR search successful".to_string()); } } diff --git a/src/mods/stat_database.rs b/src/mods/stat_database.rs index e23091d..4e104b5 100644 --- a/src/mods/stat_database.rs +++ b/src/mods/stat_database.rs @@ -1,61 +1,36 @@ use crate::{err_unrec, inf}; -use std::{fs, env}; - -pub fn stat_create_database() { - let homepath = env::var("HOME").unwrap(); - let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); - if !std::path::Path::new(&format!("{}/.local/share/ame/", env::var("HOME").unwrap())).is_dir() { - let _cdar = fs::create_dir_all(format!("/{}/.local/ame/",homepath)); - match _cdar { - Ok(_) => { - inf("Created path for database (previously missing)".to_string()); - } - Err(_) => { - err_unrec("Couldn't create path for database (~/.local/share/ame)".to_string()) - } - } - } - let connection = sqlite::open(file).unwrap(); - connection.execute( - " - CREATE TABLE static_pkgs (name TEXT, pin INTEGER); - ", - ) - .unwrap(); -} +use std::env; pub fn stat_dump_dat() -> Vec { - let homepath = env::var("HOME").unwrap(); let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); let connection = sqlite::open(file).unwrap(); let mut dat_pkgs = Vec::new(); let result = connection .iterate("SELECT name FROM static_pkgs", |pairs| { - for &(column, value) in pairs.iter() { + for &(_column, value) in pairs.iter() { dat_pkgs.push(value.unwrap().to_string()); } true }); match result { Ok(_) => { - //nf("Dumped static packages".to_string()); + //inf("Dumped static packages".to_string()); } Err(_) => { err_unrec("Couldn't dump packages from database".to_string()) } } - return dat_pkgs; + dat_pkgs } pub fn stat_get_value(pkg: &str, sear_value: &str) -> bool { let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); let connection = sqlite::open(file).unwrap(); let mut return_val = false; - //println!("{}", pkg); match sear_value { "name" => { let result = connection.iterate(format!("SELECT name FROM static_pkgs WHERE name = \"{}\";",&pkg), |pairs| { - for &(column, value) in pairs.iter() { + for &(_column, _value) in pairs.iter() { return_val = true; } return_val @@ -65,11 +40,11 @@ pub fn stat_get_value(pkg: &str, sear_value: &str) -> bool { Ok(_) => {}, Err(_) => err_unrec("Couldn't get value from database".to_string()), } - return return_val == true; + return return_val; }, "update" => { let result = connection.iterate(format!("SELECT pin FROM static_pkgs WHERE name = \"{}\";",&pkg), |pairs| { - for &(column, value) in pairs.iter() { + for &(_column, _value) in pairs.iter() { return_val = true; } return_val @@ -79,16 +54,16 @@ pub fn stat_get_value(pkg: &str, sear_value: &str) -> bool { Ok(_) => {}, Err(_) => err_unrec("Couldn't get value from database".to_string()), } - return return_val == true + return return_val }, _ => { return_val = false } } - return return_val; + return_val } -pub fn stat_rem_pkg(static_pkgs: &Vec) { +pub fn stat_rem_pkg(static_pkgs: &[String]) { let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); let connection = sqlite::open(file).unwrap(); print!("{:?}",static_pkgs); diff --git a/src/mods/statpkgs.rs b/src/mods/statpkgs.rs index 989763d..9307c2d 100644 --- a/src/mods/statpkgs.rs +++ b/src/mods/statpkgs.rs @@ -1,10 +1,8 @@ use std::{fs, env}; use crate::inf; -use toml::{Value, toml}; use crate::{ err_rec, stat_add_pkg, - stat_create_database, stat_get_value, stat_rem_pkg, inssort, @@ -13,19 +11,26 @@ use crate::{ }; pub fn rebuild(noconfirm: bool) { - let homepath = env::var("HOME").unwrap(); let file = format!("{}/.config/ame/pkgs.toml", env::var("HOME").unwrap()); - let mut database = String::new(); - database = fs::read_to_string(&file).expect("Can't Open Database"); + let database = fs::read_to_string(&file).expect("Can't Open Database"); inf("installing crystal config".to_string()); + let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap()); + let connection = sqlite::open(file).unwrap(); + connection.execute( + " + CREATE TABLE IF NOT EXISTS static_pkgs (name TEXT, pin INTEGER); + ", + ) + .unwrap(); + let db_parsed = database.parse::().expect("Invalid Database"); let mut pkgs = Vec::new(); - for entry in db_parsed.as_table() { + if let Some(entry) = db_parsed.as_table() { for (key, value) in &*entry { let mut tempvec = Vec::new(); - println!("{}", key); - println!("{}", format!("{}",value).replace("update = ", "")); + // println!("{}", key); + // println!("{}", format!("{}",value).replace("update = ", "")); tempvec.push(key.to_string()); tempvec.push(format!("{}",value).replace("update = ", "")); pkgs.push(tempvec); @@ -35,15 +40,13 @@ pub fn rebuild(noconfirm: bool) { let mut pkgs_to_install: Vec = Vec::new(); for i in pkgs { if !stat_get_value(&i[0], "name") { - let mut tempvec = Vec::new(); - tempvec.push(i[0].to_string()); - tempvec.push(i[1].to_string()); + let tempvec = vec![i[0].to_string(), i[1].to_string()]; pkgs_to_add.push(tempvec); pkgs_to_install.push(i[0].to_string()); } } let mut config_no_change = 0; - if pkgs_to_install.len() > 0 { + if !pkgs_to_install.is_empty() { inf(format!("Installing {}", pkgs_to_install.join(", "))); inssort(noconfirm, false, pkgs_to_install); for i in pkgs_to_add { @@ -54,8 +57,8 @@ pub fn rebuild(noconfirm: bool) { let dat_pkgs = stat_dump_dat(); let mut pkgs = Vec::new(); - for entry in db_parsed.as_table() { - for (key, value) in &*entry { + if let Some(entry) = db_parsed.as_table() { + for (key, _value) in &*entry { pkgs.push(key); } } @@ -67,7 +70,7 @@ pub fn rebuild(noconfirm: bool) { } config_no_change += 1; } - if pkgs_to_remove.len() > 0 { + if !pkgs_to_remove.is_empty() { inf(format!("Removing {}", pkgs_to_remove.join(", "))); stat_rem_pkg(&pkgs_to_remove); uninstall(noconfirm, pkgs_to_remove); diff --git a/src/mods/uninstall.rs b/src/mods/uninstall.rs index ec3f038..5974f1d 100644 --- a/src/mods/uninstall.rs +++ b/src/mods/uninstall.rs @@ -11,6 +11,43 @@ pub fn uninstall(noconfirm: bool, pkgs: Vec) { "Attempting to uninstall packages: {}", &pkgs.join(" ") )); + + let important = [ + "base", + "linux", + "linux-firmware", + "systemd-sysvcompat", + "networkmanager", + "man-db", + "man-pages", + "texinfo", + "sudo", + "curl", + "archlinux-keyring", + "btrfs-progs", + "timeshift", + "timeshift-autosnap" + ]; + + let mut overrides: Vec = Vec::new(); + if Path::new("/etc/ame/overrides.conf").exists() { + overrides = fs::read_to_string("/etc/ame/overrides.conf") + .expect("Failed to read overrides.conf") + .lines() + .map(|s| s.to_string()) + .collect(); + } + + let mut matches: Vec = Vec::new(); + for pkg in pkgs.iter() { + for imp in important.iter() { + if pkg == imp && !overrides.contains(pkg) { + matches.push(pkg.to_string()); + } + } + } + err_unrec(format!("The action you called for tries to uninstall packages: {} . This is disallowed by default as these are important system packages. If you fully know what you are doing and would like to uninstall these, please create an override in /etc/ame/overrides.conf.", matches.join(" "))); + if noconfirm { let result = Command::new("pacman") .arg("-Ru") diff --git a/src/mods/upgrade.rs b/src/mods/upgrade.rs index 8f34360..8e3ae8e 100644 --- a/src/mods/upgrade.rs +++ b/src/mods/upgrade.rs @@ -1,6 +1,6 @@ use crate::{ err_rec, err_unrec, inf, inssort, mods::database::get_value, mods::strs::prompt, - mods::strs::sec, mods::strs::succ, uninstall, + mods::strs::sec, mods::strs::succ, uninstall, mods::rpc::* }; use runas::Command; use std::{env, fs, path::Path}; @@ -8,7 +8,7 @@ use toml; fn uninstall_make_depend(pkg: &str) { // uninstall make depends installed by ame itself - let make_depends = raur::info(&[&pkg]).unwrap()[0].make_depends.clone(); + let make_depends = rpcinfo(pkg).make_depends; if !make_depends.is_empty() { inf(format!( @@ -78,12 +78,11 @@ pub fn upgrade(noconfirm: bool) { if let Some(entry) = db_parsed.as_table() { for (key, _value) in &*entry { - let results = raur::search(key.to_string()); - if let Ok(res) = results { + let results = rpcsearch(&key.to_string()).results; let url = format!("https://aur.archlinux.org/{}.git", key); - let package = raur::info(&[key]).unwrap(); + let package = rpcinfo(&key.to_string()); let version = get_value(key, "version"); - if res[0].version.contains(&version) { + if results[0].version.contains(&version) { let keydir = format!("{}{}", &cachedir, &key); if Path::new(&keydir).is_dir() { let cd_result = env::set_current_dir(&keydir); @@ -91,7 +90,7 @@ pub fn upgrade(noconfirm: bool) { Ok(_) => inf("Entered package directory".to_string()), Err(_) => err_unrec("Could not enter package directory".to_string()), } - inssort(true, true, package[0].depends.clone()); + inssort(true, true, package.depends.clone()); sec(format!("Installing {} ...", &key)); let install_result = std::process::Command::new("makepkg") @@ -156,7 +155,7 @@ pub fn upgrade(noconfirm: bool) { Err(_) => err_unrec("Could not enter package directory".to_string()), } - inssort(true, true, package[0].depends.clone()); + inssort(true, true, package.depends.clone()); let clone = std::process::Command::new("git") .arg("clone") @@ -211,7 +210,7 @@ pub fn upgrade(noconfirm: bool) { } else { inf(format!("Package {} already up to date", &key)); } - } + } } } diff --git a/src/mods/ver.rs b/src/mods/ver.rs index 1bc8493..3c3b16b 100644 --- a/src/mods/ver.rs +++ b/src/mods/ver.rs @@ -1,11 +1,13 @@ use crate::inf; use ansi_term::Colour; -use clap::{self, crate_version}; pub fn ver() { + + const VERSION: &str = env!("CARGO_PKG_VERSION"); + // print version and contributors println!(); - inf(format!("ame - {}", crate_version!())); + inf(format!("ame - {}", VERSION)); println!(); inf("Contributors:".to_string()); println!("- axtlos ");