diff --git a/.gitignore b/.gitignore
index 0c99807..502c7fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
target/
Cargo.lock
ame
+ame.exe
.vscode
-aur_pkgs.db
-test.sql
+.idea
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..161f3a0
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,28 @@
+# Crystal Linux Contributing Guidelines
+
+#### !! Always make sure to `git pull` before doing any work to avoid commit hell !!
+
+### Pre-Commit Checks
+
+- Make sure to `cargo fmt` your code before every commit push
+- Unless in specific edge cases, don't push code that doesn't pass `cargo check`
+- Try to correct any code with `cargo clippy` before you push
+
+### Formatting
+
+- UNIX line endings (LF instead of CRLF)
+- 4 spaces per TAB
+
+### Good Practices
+
+- Try to use .unwrap() as little as possible
+- Try to never use panic!() in production code, always try to have a possible way to resolve errors, even if it's just
+ unwrap_or/_else()
+- Never use println!() or eprintln!() in finalised code. Using string functions (e.g. info() in Amethyst v3.0.0) is
+ preferred
+- Compartmentalise as much as you can, avoid writing the exact same line of code 50 times if you can turn it into a
+ function
+
+### Examples of these guidelines in practice
+
+- https://git.getcryst.al/crystal/ame/src/branch/rewrite
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index cbbfd3d..f68234a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,19 +1,60 @@
[package]
+name = "Amethyst"
+version = "3.0.0"
+authors = ["michal ", "axtlos "]
+edition = "2021"
+description = "A fast and efficient AUR helper."
+license-file = "LICENSE.md"
+
+[features]
+pkg-warner = []
+
+[[bin]]
+name = "apt"
+path = "src/bin/apt.rs"
+required-features = ["pkg-warner"]
+
+[[bin]]
+name = "apt-get"
+path = "src/bin/apt-get.rs"
+required-features = ["pkg-warner"]
+
+[[bin]]
+name = "dnf"
+path = "src/bin/dnf.rs"
+required-features = ["pkg-warner"]
+
+[[bin]]
+name = "eopkg"
+path = "src/bin/eopkg.rs"
+required-features = ["pkg-warner"]
+
+[[bin]]
+name = "yum"
+path = "src/bin/yum.rs"
+required-features = ["pkg-warner"]
+
+[[bin]]
+name = "zypper"
+path = "src/bin/zypper.rs"
+required-features = ["pkg-warner"]
+
+[[bin]]
name = "ame"
-version = "0.0.0"
-authors = [ "jnats ", "axtlos " ]
-edition = "2018"
-description = "a fast and efficient aur helper."
+path = "src/main.rs"
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[profile.release]
+incremental = true
+debug = false
+lto = "fat"
+codegen-units = 1
[dependencies]
+mimalloc = { version = "0.1.27", default-features = false }
+clap = { version = "2.34.0", default-features = false, features = ["suggestions"] }
+regex = { version = "1.5.4", default-features = false, features = ["std", "unicode-perl"] }
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
+rusqlite = { version = "0.26.3", default-features = false }
+ureq = { version = "2.4.0", default-features = false, features = ["native-tls", "json"] }
+serde = { version = "1.0.90", default-features = false, features = ["derive", "serde_derive"] }
+native-tls = "0.2.8"
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..ba4c143
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,23 @@
+The Nolicense Revision 2.1 - Monday 15th November 2021
+
+Copyright (c) 2022 Crystal Linux Team
+
+Everyone is permitted to freely copy and distribute this license document. Modified redistributions are subject to the
+following license agreement.
+
+The Nolicense terms and conditions for copying, distribution and modification of software and any created assets are as
+follows:
+
+- Any unmodified redistributions in either source code or binary form must retain this copyright notice in its entirety.
+
+- Any and all redistributions or derivative works, whether modified or unmodified, must credit the original author(s) of
+ the source code, and provide an easily accessible way to find the original author's source code, wherever it may be
+ published.
+
+- Derivative works and modified redistributions cannot be published under the same name as the original software, nor
+ can it be presented as an extension of or newer revision of said software, and unless explicitly permitted, the
+ original authors name(s) shall not be used to endorse said derivative works.
+
+This software is provided as-is; Neither the copyright holders nor any contributors to the software are to be held
+liable for any damages caused by any files attached. By modifying or redistributing the software in any way, you
+automatically agree to the terms of the license agreement.
diff --git a/Makefile b/Makefile
deleted file mode 100644
index c8c0e52..0000000
--- a/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-debug:
- cargo build
- ln -sf target/debug/ame .
-release:
- cargo build --release
- ln -sf target/release/ame .
-clean:
- rm -rf target/ Cargo.lock ame
-install:
- cargo build --release
- sudo cp target/release/ame /usr/bin/ame
diff --git a/README.md b/README.md
index ae91791..7c005af 100644
--- a/README.md
+++ b/README.md
@@ -3,49 +3,66 @@
-
+
Amethyst
-
+
-
+
+
+
+
+Amethyst is a fast, efficient and lightweight AUR helper and Pacman wrapper.
+Made for Crystal, compatible with any Arch-based Linux distribution.
+
+
+### Basic usage
- Amethyst is a fast, efficient and lightweight AUR helper and Pacman wrapper.
-Made for Crystal, compatible with any Arch-based Linux distribution.
+| Action | FreeBSD pkg-style alias | Pacman-style flags |
+|----------------------|-------------------------|--------------------|
+| Install a package | ame ins/install | ame -S |
+| Remove a package | ame rm/remove | ame -R/-Rs |
+| Upgrade a package | ame upg/upgrade | ame -Syu |
+| Search for a package | ame sea | ame -Ss |
-![](screenshot.png)
+### Exit codes overview
-## Basic usage
-| Action | FreeBSD pkg-style alias | Pacman-style flag(s) |
-| ------ | ------ | ------ |
-| Install a package | ame ins | ame -S |
-| Remove a package | ame rm | ame -R |
-| Remove a package with its dependencies | ame purge | ame -Rs |
-| Update repository | ame upd | ame -Sy |
-| Upgrade a package | ame upg | ame -Syu |
-| Search for a package in general | ame sea | ame -Ss |
-| Search for a package in the official arch repos | ame repsea | ame -Sr |
-| Search for a package in aur | ame aursea | ame -Sa |
+| Exit Code (i32) | Reason |
+|-----------------|----------------------------------------------------------|
+| 1 | Running ame as UID 0 / root |
+| 2 | Failed adding package to database |
+| 3 | Failed initialising database |
+| 4 | Error creating cache and/or database paths |
+| 5 | Could not find one or more required package dependencies |
+| 6 | User cancelled package installation |
+| 7 | Pacman error when installing package |
-You can also use any pacman flag!
+### How to build:
-## How to build:
-(Install cargo)
+Tested on latest Cargo (1.60.0-nightly)
-For release:
- - `make clean release`
-
-For general debug/test:
- - `make debug`
+
+
+#### Debug/development builds
+
+- `cargo build`
+
+#### Optimised/release builds
+
+- `cargo build --release`
-Clean all build directories:
- - `make clean`
+#### Pkg-warner included
+
+- `cargo build (--release) --all --features=pkg-warner`
-```sh
-echo "AME_UWU=YES" >> ~/.zshrc # for zsh
-echo "AME_UWU=YES" >> ~/.bashrc # for bash
-set -Ux AME_UWU YES # for fish
-```
-self explanatory
+
\ No newline at end of file
diff --git a/src/bin/apt-get.rs b/src/bin/apt-get.rs
new file mode 100644
index 0000000..db60a1d
--- /dev/null
+++ b/src/bin/apt-get.rs
@@ -0,0 +1,14 @@
+use std::env;
+
+fn main() {
+ let arg = &env::args().collect::>()[0];
+
+ println!(
+ "Sorry for the bother, we don't use \x1b[2;22;35m{}\x1b[0m on Crystal, we use \x1b[2;22;35mame\x1b[0m! Please use that instead!",
+ arg.split('/')
+ .collect::>()
+ .last()
+ .unwrap()
+ );
+ std::process::exit(0);
+}
diff --git a/src/bin/apt.rs b/src/bin/apt.rs
new file mode 100644
index 0000000..db60a1d
--- /dev/null
+++ b/src/bin/apt.rs
@@ -0,0 +1,14 @@
+use std::env;
+
+fn main() {
+ let arg = &env::args().collect::>()[0];
+
+ println!(
+ "Sorry for the bother, we don't use \x1b[2;22;35m{}\x1b[0m on Crystal, we use \x1b[2;22;35mame\x1b[0m! Please use that instead!",
+ arg.split('/')
+ .collect::>()
+ .last()
+ .unwrap()
+ );
+ std::process::exit(0);
+}
diff --git a/src/bin/dnf.rs b/src/bin/dnf.rs
new file mode 100644
index 0000000..db60a1d
--- /dev/null
+++ b/src/bin/dnf.rs
@@ -0,0 +1,14 @@
+use std::env;
+
+fn main() {
+ let arg = &env::args().collect::>()[0];
+
+ println!(
+ "Sorry for the bother, we don't use \x1b[2;22;35m{}\x1b[0m on Crystal, we use \x1b[2;22;35mame\x1b[0m! Please use that instead!",
+ arg.split('/')
+ .collect::>()
+ .last()
+ .unwrap()
+ );
+ std::process::exit(0);
+}
diff --git a/src/bin/eopkg.rs b/src/bin/eopkg.rs
new file mode 100644
index 0000000..db60a1d
--- /dev/null
+++ b/src/bin/eopkg.rs
@@ -0,0 +1,14 @@
+use std::env;
+
+fn main() {
+ let arg = &env::args().collect::>()[0];
+
+ println!(
+ "Sorry for the bother, we don't use \x1b[2;22;35m{}\x1b[0m on Crystal, we use \x1b[2;22;35mame\x1b[0m! Please use that instead!",
+ arg.split('/')
+ .collect::>()
+ .last()
+ .unwrap()
+ );
+ std::process::exit(0);
+}
diff --git a/src/bin/yum.rs b/src/bin/yum.rs
new file mode 100644
index 0000000..db60a1d
--- /dev/null
+++ b/src/bin/yum.rs
@@ -0,0 +1,14 @@
+use std::env;
+
+fn main() {
+ let arg = &env::args().collect::>()[0];
+
+ println!(
+ "Sorry for the bother, we don't use \x1b[2;22;35m{}\x1b[0m on Crystal, we use \x1b[2;22;35mame\x1b[0m! Please use that instead!",
+ arg.split('/')
+ .collect::>()
+ .last()
+ .unwrap()
+ );
+ std::process::exit(0);
+}
diff --git a/src/bin/zypper.rs b/src/bin/zypper.rs
new file mode 100644
index 0000000..db60a1d
--- /dev/null
+++ b/src/bin/zypper.rs
@@ -0,0 +1,14 @@
+use std::env;
+
+fn main() {
+ let arg = &env::args().collect::>()[0];
+
+ println!(
+ "Sorry for the bother, we don't use \x1b[2;22;35m{}\x1b[0m on Crystal, we use \x1b[2;22;35mame\x1b[0m! Please use that instead!",
+ arg.split('/')
+ .collect::>()
+ .last()
+ .unwrap()
+ );
+ std::process::exit(0);
+}
diff --git a/src/database/add.rs b/src/database/add.rs
new file mode 100644
index 0000000..eaea9d6
--- /dev/null
+++ b/src/database/add.rs
@@ -0,0 +1,26 @@
+use std::env;
+use std::path::Path;
+
+use rusqlite::Connection;
+
+use crate::{crash, log, Options};
+use crate::internal::rpc::Package;
+
+pub fn add(pkg: Package, options: Options) {
+ let conn = Connection::open(Path::new(&format!(
+ "{}/.local/share/ame/db.sqlite",
+ env::var("HOME").unwrap()
+ )))
+ .expect("Couldn't connect to database");
+
+ if options.verbosity >= 1 {
+ log(format!("Adding package {} to database", pkg.name));
+ }
+
+ 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(" ")],
+ ).unwrap_or_else(|e| {
+ crash(format!("Failed adding package {} to the database: {}", pkg.name, e), 2);
+ 1
+ });
+}
diff --git a/src/database/initialise.rs b/src/database/initialise.rs
new file mode 100644
index 0000000..d7121a6
--- /dev/null
+++ b/src/database/initialise.rs
@@ -0,0 +1,38 @@
+use std::env;
+use std::path::Path;
+
+use rusqlite::Connection;
+
+use crate::{crash, log, Options};
+
+pub fn init(options: Options) {
+ let path = format!("{}/.local/share/ame/db.sqlite", env::var("HOME").unwrap());
+ let dbpath = Path::new(&path);
+ let verbosity = options.verbosity;
+
+ if verbosity >= 1 {
+ log(format!("Creating database at {}", &path));
+ }
+
+ let conn =
+ Connection::open(dbpath).expect("Couldn't create database at ~/.local/share/ame/db.sqlite");
+
+ if verbosity >= 1 {
+ log("Populating database with table".to_string());
+ }
+
+ conn.execute(
+ "CREATE TABLE packages (
+ name TEXT PRIMARY KEY NOT NULL,
+ version TEXT NOT NULL,
+ description TEXT,
+ depends BLOB,
+ make_depends BLOB
+ )",
+ [],
+ )
+ .unwrap_or_else(|e| {
+ crash(format!("Couldn't initialise database: {}", e), 3);
+ 1
+ });
+}
\ No newline at end of file
diff --git a/src/database/mod.rs b/src/database/mod.rs
new file mode 100644
index 0000000..0e79ed6
--- /dev/null
+++ b/src/database/mod.rs
@@ -0,0 +1,23 @@
+use crate::internal::rpc::Package;
+use crate::Options;
+
+mod add;
+mod initialise;
+mod query;
+mod remove;
+
+pub fn add(a: Package, options: Options) {
+ add::add(a, options);
+}
+
+pub fn remove(a: &str, options: Options) {
+ remove::remove(a, options);
+}
+
+pub fn init(options: Options) {
+ initialise::init(options);
+}
+
+pub fn query(options: Options) -> Vec {
+ query::query(options)
+}
diff --git a/src/database/query.rs b/src/database/query.rs
new file mode 100644
index 0000000..6626fa7
--- /dev/null
+++ b/src/database/query.rs
@@ -0,0 +1,64 @@
+use std::env;
+use std::path::Path;
+
+use rusqlite::Connection;
+
+use crate::{log, Options};
+use crate::internal::rpc::Package;
+
+pub fn query(options: Options) -> Vec {
+ let verbosity = options.verbosity;
+
+ if verbosity >= 1 {
+ log("Connecting to database".to_string());
+ }
+
+ let conn = Connection::open(Path::new(&format!(
+ "{}/.local/share/ame/db.sqlite",
+ env::var("HOME").unwrap()
+ )))
+ .expect("Couldn't connect to database");
+
+ if verbosity >= 1 {
+ log("Querying database for input".to_string());
+ }
+
+ let mut rs = conn.prepare("SELECT * FROM packages;").unwrap();
+ let packages_iter = rs
+ .query_map([], |row| {
+ Ok(Package {
+ name: row.get(0).unwrap(),
+ version: row.get(1).unwrap(),
+ description: row.get(2).unwrap(),
+ depends: row
+ .get::(3)
+ .unwrap()
+ .split(' ')
+ .map(|s| s.to_string())
+ .collect::>(),
+ make_depends: row
+ .get::(4)
+ .unwrap()
+ .split(' ')
+ .map(|s| s.to_string())
+ .collect::>(),
+ })
+ })
+ .expect("Couldn't query database for packages");
+
+ if verbosity >= 1 {
+ log("Retrieved results".to_string());
+ }
+
+ let mut results: Vec = vec![];
+
+ for package in packages_iter {
+ results.push(package.unwrap());
+ }
+
+ if verbosity >= 1 {
+ log("Collected results".to_string());
+ }
+
+ results
+}
diff --git a/src/database/remove.rs b/src/database/remove.rs
new file mode 100644
index 0000000..c213e3b
--- /dev/null
+++ b/src/database/remove.rs
@@ -0,0 +1,30 @@
+use std::env;
+use std::path::Path;
+
+use rusqlite::Connection;
+
+use crate::{log, Options};
+
+pub fn remove(pkg: &str, options: Options) {
+ let conn = Connection::open(Path::new(&format!(
+ "{}/.local/share/ame/db.sqlite",
+ env::var("HOME").unwrap()
+ )))
+ .expect("Couldn't connect to database");
+
+ let verbosity = options.verbosity;
+
+ if verbosity >= 1 {
+ log(format!("Removing package {} from database", pkg));
+ }
+
+ conn.execute(
+ "DELETE FROM packages
+ WHERE EXISTS
+ (SELECT *
+ FROM packages
+ WHERE name = ?);",
+ [pkg],
+ )
+ .expect("Couldn't delete package from database");
+}
diff --git a/src/internal/clean.rs b/src/internal/clean.rs
new file mode 100644
index 0000000..f6fbcc5
--- /dev/null
+++ b/src/internal/clean.rs
@@ -0,0 +1,25 @@
+use regex::Regex;
+
+use crate::internal::strings::log;
+use crate::Options;
+
+pub fn clean(a: &[String], options: Options) -> Vec {
+ let r = Regex::new(r"(\S+)((?:>=|<=|>|<)\S+$)").unwrap();
+ let mut cleaned: Vec = vec![];
+ let verbosity = options.verbosity;
+
+ for b in a {
+ if r.captures_iter(b).count() > 0 {
+ let c = r.captures(b).unwrap().get(1).map_or("", |m| m.as_str());
+ cleaned.push(c.to_string());
+ } else {
+ cleaned.push(b.to_string());
+ }
+ }
+
+ if verbosity >= 1 {
+ log(format!("Cleaned: {:?}\nInto: {:?}", a, cleaned));
+ }
+
+ cleaned
+}
diff --git a/src/internal/initialise.rs b/src/internal/initialise.rs
new file mode 100644
index 0000000..d48eec6
--- /dev/null
+++ b/src/internal/initialise.rs
@@ -0,0 +1,48 @@
+use std::env;
+use std::path::Path;
+
+use crate::internal::strings::{crash, log};
+use crate::Options;
+
+pub fn init(options: Options) {
+ let verbosity = options.verbosity;
+ let homedir = env::var("HOME").unwrap();
+
+ if !Path::new(&format!("{}/.local/share/ame", homedir)).exists() {
+ let r = std::fs::create_dir_all(format!("{}/.local/share/ame", homedir));
+ match r {
+ Ok(_) => {
+ if verbosity >= 1 {
+ log(format!("Created path: {}/.local/share/ame", homedir));
+ }
+ }
+ Err(e) => {
+ crash(
+ format!("Couldn't create path: {}/.local/share/ame: {}", homedir, e),
+ 4,
+ );
+ }
+ }
+ }
+
+ if !Path::new(&format!("{}/.local/share/ame/db.sqlite", homedir)).exists() {
+ crate::database::init(options);
+ }
+
+ if !Path::new(&format!("{}/.cache/ame/", homedir)).exists() {
+ let r = std::fs::create_dir_all(format!("{}/.cache/ame", homedir));
+ match r {
+ Ok(_) => {
+ if verbosity >= 1 {
+ log(format!("Created path: {}/.cache/ame", homedir));
+ }
+ }
+ Err(e) => {
+ crash(
+ format!("Couldn't create path: {}/.cache/ame: {}", homedir, e),
+ 4,
+ );
+ }
+ }
+ }
+}
diff --git a/src/internal/mod.rs b/src/internal/mod.rs
new file mode 100644
index 0000000..06c7006
--- /dev/null
+++ b/src/internal/mod.rs
@@ -0,0 +1,53 @@
+use crate::Options;
+
+mod clean;
+mod initialise;
+pub mod rpc;
+mod sort;
+mod strings;
+pub mod structs;
+
+pub fn sort(a: &[String], options: Options) -> structs::Sorted {
+ sort::sort(a, options)
+}
+
+pub fn clean(a: &[String], options: Options) -> Vec {
+ clean::clean(a, options)
+}
+
+pub fn init(options: Options) {
+ initialise::init(options);
+}
+
+pub fn info(a: String) {
+ strings::info(a);
+}
+
+pub fn crash(a: String, b: i32) {
+ strings::crash(a, b);
+}
+
+pub fn log(a: String) {
+ strings::log(a);
+}
+
+pub fn prompt(a: String, b: bool) -> bool {
+ strings::prompt(a, b)
+}
+
+#[macro_export]
+macro_rules! uwu {
+ ($x:expr) => {{
+ let uwu: String = String::from_str($x).unwrap();
+
+ let uwu = uwu.replace("l", "w");
+ let uwu = uwu.replace("L", "W");
+ let uwu = uwu.replace("r", "w");
+ let uwu = uwu.replace("R", "W");
+ let uwu = uwu.replace("na", "nya");
+ let uwu = uwu.replace("Na", "Nya");
+ let uwu = uwu.replace("NA", "NYA");
+
+ uwu
+ }};
+}
diff --git a/src/internal/rpc.rs b/src/internal/rpc.rs
new file mode 100644
index 0000000..341d32a
--- /dev/null
+++ b/src/internal/rpc.rs
@@ -0,0 +1,75 @@
+use std::sync::Arc;
+
+#[derive(serde::Deserialize, Debug, Clone)]
+pub struct Package {
+ #[serde(rename = "Name")]
+ pub name: String,
+ #[serde(rename = "Version")]
+ pub version: String,
+ #[serde(rename = "Description")]
+ pub description: Option,
+ #[serde(rename = "Depends")]
+ #[serde(default)]
+ pub depends: Vec,
+ #[serde(rename = "MakeDepends")]
+ #[serde(default)]
+ pub make_depends: Vec,
+}
+
+#[derive(serde::Deserialize)]
+pub struct SearchResults {
+ pub resultcount: u32,
+ pub results: Vec,
+}
+
+#[derive(Clone)]
+pub struct InfoResults {
+ pub found: bool,
+ pub package: Option,
+}
+
+pub const URL: &str = "https://aur.archlinux.org/";
+
+pub fn rpcinfo(pkg: String) -> InfoResults {
+ let tls_connector = Arc::new(native_tls::TlsConnector::new().unwrap());
+ let agent = ureq::AgentBuilder::new()
+ .tls_connector(tls_connector)
+ .build();
+ let res: SearchResults = agent
+ .get(&format!(
+ "https://aur.archlinux.org/rpc/?v=5&type=info&arg={}",
+ pkg
+ ))
+ .call()
+ .unwrap()
+ .into_json()
+ .unwrap();
+
+ if res.results.is_empty() {
+ InfoResults {
+ found: false,
+ package: None,
+ }
+ } else {
+ InfoResults {
+ found: true,
+ package: Some(res.results[0].clone()),
+ }
+ }
+}
+
+pub fn rpcsearch(pkg: String) -> SearchResults {
+ let tls_connector = Arc::new(native_tls::TlsConnector::new().unwrap());
+ let agent = ureq::AgentBuilder::new()
+ .tls_connector(tls_connector)
+ .build();
+ agent
+ .get(&format!(
+ "https://aur.archlinux.org/rpc/?v=5&type=search&arg={}",
+ pkg
+ ))
+ .call()
+ .unwrap()
+ .into_json::()
+ .unwrap()
+}
diff --git a/src/internal/sort.rs b/src/internal/sort.rs
new file mode 100644
index 0000000..56c3cac
--- /dev/null
+++ b/src/internal/sort.rs
@@ -0,0 +1,46 @@
+use std::process::{Command, Stdio};
+
+use crate::internal::{clean, rpc, structs};
+use crate::internal::strings::log;
+use crate::Options;
+
+pub fn sort(input: &[String], options: Options) -> structs::Sorted {
+ let mut repo: Vec = vec![];
+ let mut aur: Vec = vec![];
+ let mut nf: Vec = vec![];
+ let verbosity = options.verbosity;
+
+ let a = clean(input, options);
+
+ if verbosity >= 1 {
+ log(format!("Sorting: {:?}", a.join(" ")));
+ }
+
+ for b in a {
+ let rs = Command::new("pacman")
+ .arg("-Ss")
+ .arg(format!("^{}$", &b))
+ .stdout(Stdio::null())
+ .status()
+ .expect("Something has gone wrong");
+
+ if rpc::rpcinfo(b.to_string()).found {
+ if verbosity >= 1 {
+ log(format!("{} found in AUR", b));
+ }
+ aur.push(b.to_string());
+ } else if let Some(0) = rs.code() {
+ if verbosity >= 1 {
+ log(format!("{} found in repos", b));
+ }
+ repo.push(b.to_string());
+ } else {
+ if verbosity >= 1 {
+ log(format!("{} not found", b));
+ }
+ nf.push(b.to_string());
+ }
+ }
+
+ structs::Sorted::new(repo, aur, nf)
+}
diff --git a/src/internal/strings.rs b/src/internal/strings.rs
new file mode 100644
index 0000000..1883226
--- /dev/null
+++ b/src/internal/strings.rs
@@ -0,0 +1,76 @@
+use std::{env, io};
+use std::io::Write;
+use std::process::exit;
+use std::str::FromStr;
+use std::time::UNIX_EPOCH;
+
+use crate::uwu;
+
+pub fn info(a: String) {
+ let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" {
+ uwu!(&a)
+ } else {
+ a
+ };
+
+ println!("\x1b[2;22;35m❖\x1b[0m \x1b[1;37m{}\x1b[0m", a)
+}
+
+pub fn crash(a: String, b: i32) {
+ let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" {
+ uwu!(&a)
+ } else {
+ a
+ };
+
+ println!("\x1b[2;22;31m❌:\x1b[0m \x1b[1;91m{}\x1b[0m", a);
+ exit(b);
+}
+
+pub fn log(a: String) {
+ let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true"
+ && env::var("AME_UWU_DEBUG").unwrap_or_else(|_| "".to_string()) == "true"
+ {
+ uwu!(&a)
+ } else {
+ a
+ };
+
+ eprintln!(
+ "{} {}",
+ std::time::SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_secs(),
+ a
+ );
+}
+
+pub fn prompt(a: String, b: bool) -> bool {
+ let default = ["[Y/n]", "[y/N]"];
+ let i = if b { 0 } else { 1 };
+
+ let a = if env::var("AME_UWU").unwrap_or_else(|_| "".to_string()) == "true" {
+ uwu!(&a)
+ } else {
+ a
+ };
+
+ print!(
+ "\x1b[2;22;35m?\x1b[0m \x1b[1;37m{}\x1b[0m \x1b[2;22;37m{}\x1b[0m: ",
+ a, default[i]
+ );
+
+ let mut yn: String = String::new();
+
+ io::stdout().flush().ok();
+ let _ = std::io::stdin().read_line(&mut yn);
+
+ if yn.trim().to_lowercase() == "n" || yn.trim().to_lowercase() == "no" {
+ false
+ } else if yn.trim().to_lowercase() == "y" || yn.trim().to_lowercase() == "yes" {
+ true
+ } else {
+ b
+ }
+}
diff --git a/src/internal/structs.rs b/src/internal/structs.rs
new file mode 100644
index 0000000..7fd8007
--- /dev/null
+++ b/src/internal/structs.rs
@@ -0,0 +1,23 @@
+#[derive(Debug, serde::Serialize)]
+pub struct Sorted {
+ #[allow(dead_code)]
+ pub repo: Vec,
+ #[allow(dead_code)]
+ pub aur: Vec,
+ #[allow(dead_code)]
+ pub nf: Vec,
+}
+
+impl Sorted {
+ pub fn new(repo: Vec, aur: Vec, nf: Vec) -> Self {
+ let a: Sorted = Sorted { repo, aur, nf };
+ a
+ }
+}
+
+#[derive(Clone, Copy)]
+pub struct Options {
+ pub verbosity: i32,
+ pub noconfirm: bool,
+ pub asdeps: bool,
+}
diff --git a/src/main.rs b/src/main.rs
index c38eba5..3a7f7f2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,25 +1,16 @@
-mod mods;
-use mods::{
- clearcache::clearcache,
- clone::clone,
- database::create_database,
- help::help,
- inssort::{inssort, inssort_from_file},
- install::install,
- purge::{purge, purge_from_file},
- search::{a_search, r_search},
- stat_database::*,
- statpkgs::*,
- strs::err_rec,
- strs::err_unrec,
- strs::inf,
- uninstall::{uninstall, uninstall_from_file},
- update::update,
- upgrade::upgrade,
- ver::ver,
- xargs::*,
-};
-use std::{env, process::exit};
+use std::io;
+use std::process::{exit, Command};
+
+use clap::{App, AppSettings, Arg, ArgMatches, ArgSettings, Shell, SubCommand};
+
+use crate::internal::{crash, info, init, log, sort, structs::Options};
+
+#[global_allocator]
+static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
+
+mod database;
+mod internal;
+mod operations;
fn main() {
extern "C" {
@@ -27,92 +18,287 @@ fn main() {
}
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(),
- );
+ crash("Running amethyst as root is disallowed as it can lead to system breakage. Instead, amethyst will prompt you when it needs superuser permissions".to_string(), 1);
}
- let args: Vec = env::args().skip(1).collect();
- let mut pkgs: Vec = env::args().skip(2).collect();
-
- if args.is_empty() {
- help();
- exit(1);
+ fn build_app() -> App<'static, 'static> {
+ let app = App::new("Amethyst")
+ .version(env!("CARGO_PKG_VERSION"))
+ .about(env!("CARGO_PKG_DESCRIPTION"))
+ .arg(
+ Arg::with_name("verbose")
+ .short("v")
+ .long("verbose")
+ .multiple(true)
+ .set(ArgSettings::Global)
+ .help("Sets the level of verbosity"),
+ )
+ .arg(
+ Arg::with_name("noconfirm")
+ .long("noconfirm")
+ .set(ArgSettings::Global)
+ .help("Complete operation without prompting user"),
+ )
+ .subcommand(
+ SubCommand::with_name("install")
+ .about(
+ "Installs a package from either the AUR or the PacMan-defined repositories",
+ )
+ .aliases(&["-S", "ins"])
+ .arg(
+ Arg::with_name("package(s)")
+ .help("The name of the package(s) to install")
+ .required(true)
+ .multiple(true)
+ .index(1),
+ ),
+ )
+ .subcommand(
+ SubCommand::with_name("remove")
+ .about("Removes a previously installed package")
+ .aliases(&["-R", "-Rs", "rm"])
+ .arg(
+ Arg::with_name("package(s)")
+ .help("The name of the package(s) to remove")
+ .required(true)
+ .multiple(true)
+ .index(1),
+ ),
+ )
+ .subcommand(
+ SubCommand::with_name("search")
+ .about("Searches for the relevant packages in both the AUR and repos")
+ .aliases(&["-Ss", "sea"])
+ .arg(
+ Arg::with_name("aur")
+ .short("a")
+ .long("aur")
+ .help("Search only the AUR for the package"),
+ )
+ .arg(
+ Arg::with_name("repo")
+ .short("r")
+ .long("repo")
+ .help("Searches only local repos for the package"),
+ )
+ .arg(
+ Arg::with_name("package(s)")
+ .help("The name of the package to search for")
+ .required(true)
+ .multiple(false)
+ .index(1),
+ ),
+ )
+ .subcommand(
+ SubCommand::with_name("query")
+ .about("Queries installed packages")
+ .aliases(&["-Q", "ls"])
+ .arg(
+ Arg::with_name("aur")
+ .short("a")
+ .help("Lists AUR/foreign packages"),
+ )
+ .arg(
+ Arg::with_name("repo")
+ .short("r")
+ .help("Lists repo/native packages"),
+ ),
+ )
+ .subcommand(
+ SubCommand::with_name("upgrade")
+ .about("Upgrades locally installed packages to their latest versions")
+ .aliases(&["-Syu", "upg"]),
+ )
+ .subcommand(
+ SubCommand::with_name("compgen")
+ .about("Generates shell completions for given shell (bash by default)")
+ .aliases(&["-G", "cg"])
+ .arg(
+ Arg::with_name("shell")
+ .help("The name of the shell you want to generate completions for")
+ .possible_values(&["bash", "fish", "zsh", "pwsh", "elvish"])
+ .required(true),
+ ),
+ )
+ .settings(&[
+ AppSettings::GlobalVersion,
+ AppSettings::VersionlessSubcommands,
+ AppSettings::ArgRequiredElseHelp,
+ AppSettings::InferSubcommands,
+ ]);
+ app
}
- let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap());
- if !std::path::Path::new(&file).exists() {
- create_database();
+ let matches = build_app().get_matches();
+
+ let verbosity: i32 = matches.occurrences_of("verbose") as i32;
+ let noconfirm: bool = matches.is_present("noconfirm");
+
+ let options = Options {
+ verbosity,
+ noconfirm,
+ asdeps: false,
+ };
+
+ init(options);
+
+ fn collect_matches(a: &ArgMatches) -> Vec {
+ a.subcommand()
+ .1
+ .unwrap()
+ .values_of("package(s)")
+ .unwrap()
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect()
}
- let oper = &args[0];
- let noconfirm: bool = noconf(&args);
+ if let true = matches.is_present("install") {
+ let packages = collect_matches(&matches);
+ let sorted = sort(&packages, options);
- argssort(&mut pkgs);
- match oper.as_str() {
- // match oper
- "-S" | "-Sn" | "ins" => {
- inssort(noconfirm, false, pkgs); // install
- }
- "-Sl" | "-Sln" | "insl" => {
- inssort_from_file(noconfirm, false, &pkgs[0]); // install from file
- }
- "-B" | "-Bn" | "build" => {
- rebuild(noconfirm); // install as a dependency
- }
- "-R" | "-Rn" | "rm" => {
- uninstall(noconfirm, pkgs); // uninstall
- }
- "-Rs" | "-Rsn" | "purge" => {
- purge(noconfirm, pkgs); // purge
- }
- "-Rl" | "-Rln" | "rml" => {
- uninstall_from_file(noconfirm, &pkgs[0]); // uninstall from file
- }
- "-Rsl" | "-Rsln" | "purgel" => {
- purge_from_file(noconfirm, &pkgs[0]); // purge from file
+ info(format!(
+ "Attempting to install packages: {}",
+ packages.join(", ")
+ ));
+
+ if !sorted.repo.is_empty() {
+ operations::install(sorted.repo, options);
}
- "-Syu" | "-Syun" | "upg" => {
- upgrade(noconfirm); // upgrade
+ if !sorted.aur.is_empty() {
+ operations::aur_install(sorted.aur, options);
}
- "-Sy" | "upd" => {
- update(); // update
+ if !sorted.nf.is_empty() {
+ log(format!(
+ "Couldn't find packages: {} in repos or the AUR",
+ sorted.nf.join(", ")
+ ));
}
- "-Ss" | "sea" => {
- r_search(&args[1]); // search for packages in the repository
- a_search(&args[1]); // search for packages in the aur
+ exit(0);
+ }
+
+ if let true = matches.is_present("remove") {
+ let packages = collect_matches(&matches);
+ info(format!("Uninstalling packages: {}", &packages.join(", ")));
+ operations::uninstall(packages, options);
+ exit(0);
+ }
+
+ if let true = matches.is_present("upgrade") {
+ info("Performing system upgrade".to_string());
+ operations::upgrade(options);
+ exit(0);
+ }
+
+ if let true = matches.is_present("search") {
+ let packages = collect_matches(&matches);
+ if matches
+ .subcommand_matches("search")
+ .unwrap()
+ .is_present("aur")
+ {
+ info(format!("Searching AUR for {}", &packages[0]));
+ operations::aur_search(&packages[0], options);
}
- "-Sa" | "aursea" => {
- a_search(&args[1]); // search for packages in the aur
+ if matches
+ .subcommand_matches("search")
+ .unwrap()
+ .is_present("repo")
+ {
+ info(format!("Searching repos for {}", &packages[0]));
+ operations::search(&packages[0], options);
}
- "-Sr" | "repsea" => {
- r_search(&args[1]); // search for packages in the repository
+
+ if !matches
+ .subcommand_matches("search")
+ .unwrap()
+ .is_present("repo")
+ && !matches
+ .subcommand_matches("search")
+ .unwrap()
+ .is_present("aur")
+ {
+ info(format!("Searching AUR and repos for {}", &packages[0]));
+ operations::search(&packages[0], options);
+ operations::aur_search(&packages[0], options);
}
- "-Cc" | "clr" => {
- clearcache(); // clear cache
+ exit(0);
+ }
+
+ if let true = matches.is_present("query") {
+ if matches
+ .subcommand_matches("query")
+ .unwrap()
+ .is_present("aur")
+ {
+ Command::new("pacman")
+ .arg("-Qm")
+ .spawn()
+ .expect("Something has gone wrong")
+ .wait()
+ .unwrap();
}
- "-v" | "-V" | "ver" => {
- ver(); // version
+ if matches
+ .subcommand_matches("query")
+ .unwrap()
+ .is_present("repo")
+ {
+ Command::new("pacman")
+ .arg("-Qn")
+ .spawn()
+ .expect("Something has gone wrong")
+ .wait()
+ .unwrap();
}
- "-h" | "help" => {
- help(); // help
+ if !matches
+ .subcommand_matches("query")
+ .unwrap()
+ .is_present("aur")
+ && !matches
+ .subcommand_matches("query")
+ .unwrap()
+ .is_present("repo")
+ {
+ Command::new("pacman")
+ .arg("-Qn")
+ .spawn()
+ .expect("Something has gone wrong")
+ .wait()
+ .unwrap();
+ Command::new("pacman")
+ .arg("-Qm")
+ .spawn()
+ .expect("Something has gone wrong")
+ .wait()
+ .unwrap();
}
- _ => {
- // if oper is not valid it either passes the args to pacman or prints an error
- let pass = runas::Command::new("pacman")
- .args(&args)
- .status()
- .expect("Something has gone wrong.");
-
- match pass.code() {
- Some(1) => {
- err_rec(format!("No such operation \"{}\"", args.join(" ")));
- inf("Try running \"ame help\" for an overview of how to use ame".to_string())
- }
- Some(_) => {}
- None => err_unrec("Something has gone terribly wrong.".to_string()),
+ exit(0);
+ }
+
+ if let true = &matches.is_present("compgen") {
+ let mut app = build_app();
+ match matches
+ .subcommand_matches("compgen")
+ .unwrap()
+ .value_of("shell")
+ .unwrap()
+ {
+ "bash" => {
+ app.gen_completions_to("ame", Shell::Bash, &mut io::stdout());
+ }
+ "fish" => {
+ app.gen_completions_to("ame", Shell::Fish, &mut io::stdout());
+ }
+ "zsh" => {
+ app.gen_completions_to("ame", Shell::Zsh, &mut io::stdout());
+ }
+ "pwsh" => {
+ app.gen_completions_to("ame", Shell::PowerShell, &mut io::stdout());
+ }
+ "elvish" => {
+ app.gen_completions_to("ame", Shell::Elvish, &mut io::stdout());
}
+ _ => {}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/mods.rs b/src/mods.rs
deleted file mode 100644
index f87e8c6..0000000
--- a/src/mods.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-pub mod clearcache;
-pub mod clone;
-pub mod database;
-pub mod help;
-pub mod inssort;
-pub mod install;
-pub mod purge;
-pub mod rpc;
-pub mod search;
-pub mod stat_database;
-pub mod statpkgs;
-pub mod strs;
-pub mod uninstall;
-pub mod update;
-pub mod upgrade;
-pub mod ver;
-pub mod xargs;
diff --git a/src/mods/clearcache.rs b/src/mods/clearcache.rs
deleted file mode 100644
index 86fcf46..0000000
--- a/src/mods/clearcache.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-use crate::mods::strs::err_rec;
-use std::fs;
-
-pub fn clearcache() {
- // delete all files in cache
- let path = format!("{}/.cache/ame/", std::env::var("HOME").unwrap());
-
- err_rec("Clearing cache".to_string());
-
- fs::remove_dir_all(&path).unwrap();
- fs::create_dir(&path).unwrap();
-}
diff --git a/src/mods/clone.rs b/src/mods/clone.rs
deleted file mode 100644
index 264cd1d..0000000
--- a/src/mods/clone.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-use crate::{
- err_unrec, inf, mods::database::add_pkg, mods::purge::purge, mods::rpc::*, mods::strs::prompt,
- mods::strs::sec, mods::strs::succ, inssort
-};
-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 = rpcinfo(pkg).make_depends;
-
- let explicit_packages = Command::new("pacman")
- .arg("-Qetq")
- .stdout(std::process::Stdio::piped())
- .output()
- .expect("Something has gone terribly wrong");
-
- 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 = Vec::new();
- for pkg in expl_pkgs_parse {
- 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());
- }
- };
- }
- }
-
- if !rem_pkgs.is_empty() {
- inf(format!(
- "{} installed following make dependencies: {}",
- pkg,
- rem_pkgs.join(", ")
- ));
- let remove = prompt("Would you like to remove them?".to_string());
- if remove {
- purge(true, rem_pkgs);
- }
- }
- succ(format!("Succesfully installed {}", pkg));
-}
-
-pub fn clone(noconfirm: bool, as_dep: bool, pkg: &str) {
- // clone a package from aur
- let cachedir = format!("{}/.cache/ame", env::var("HOME").unwrap());
- let path = Path::new(&cachedir);
- let pkgdir = format!("{}/{}", &cachedir, &pkg);
- let search = rpcsearch(pkg).results;
- let package = search.first().unwrap();
- 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 {
- Ok(_) => inf("Created cache path (first run)".to_string()),
- Err(_) => err_unrec("Could not create cache path".to_string()),
- }
- }
-
- inf(format!("Cloning {} ...", pkg));
-
- if Path::new(&pkgdir).is_dir() {
- let rm_result = fs::remove_dir_all(&pkgdir);
- match rm_result {
- Ok(_) => inf(format!(
- "Package path for {} already found. Removing to reinstall",
- pkg
- )),
- Err(_) => err_unrec(format!(
- "Package path for {} already found, but could not remove to reinstall",
- pkg
- )),
- }
- }
-
- let dir_result = fs::create_dir(&pkgdir);
- match dir_result {
- Ok(_) => inf(format!("Created package directory for {}", pkg)),
- Err(_) => err_unrec(format!("Couldn't create package directory for {}", pkg)),
- }
-
- let cd_result = env::set_current_dir(&pkgdir);
- match cd_result {
- Ok(_) => inf("Entered package directory".to_string()),
- Err(_) => err_unrec("Could not enter package directory".to_string()),
- }
-
- sec("Installing AUR package depends".to_string());
-
- let clone = std::process::Command::new("git")
- .arg("clone")
- .arg(&url)
- .arg(&pkgdir)
- .status()
- .expect("Couldn't clone repository");
- match clone.code() {
- Some(0) => {
- inf(format!("Cloning {} into package directory", pkg));
- }
- Some(_) => err_unrec(format!("Failed cloning {} into package directory", pkg)),
- _ => err_unrec(format!("Failed cloning {} into package directory", pkg)),
- }
- if !as_dep {
- if !noconfirm {
- let pkgbuild = prompt("View PKGBUILD?".to_string());
-
- if pkgbuild {
- let mut pkgbld = fs::read_to_string(format!("{}/PKGBUILD", &pkgdir)).unwrap();
- Moins::run(&mut pkgbld, None);
- }
- }
-
- sec(format!("Installing {} ...", pkg));
- if noconfirm {
- let install_result = Command::new("makepkg")
- .arg("-si")
- .arg("--noconfirm")
- .arg("--needed")
- .status();
- match install_result {
- Ok(_) => {
- uninstall_make_depend(pkg);
- let vec = vec![pkg];
- add_pkg(false, &vec);
- }
- Err(_) => {
- err_unrec(format!("Couldn't install {}", pkg));
- }
- };
- } else {
- let install_result = Command::new("makepkg")
- .arg("-si")
- .arg("--needed")
- .status()
- .expect("Couldn't call makepkg");
- match install_result.code() {
- Some(0) => {
- uninstall_make_depend(pkg);
- let vec = vec![pkg];
- add_pkg(false, &vec);
- }
- Some(_) => {
- err_unrec(format!("Couldn't install {}", pkg));
- }
- None => {
- err_unrec(format!("Couldn't install {}", pkg));
- }
- };
- }
- } else {
- sec(format!("Installing {} ...", pkg));
- let install_result = Command::new("makepkg")
- .arg("-si")
- .arg("--noconfirm")
- .arg("--needed")
- .arg("--asdeps")
- .status();
- match install_result {
- Ok(_) => {
- uninstall_make_depend(pkg);
- let vec = vec![pkg];
- add_pkg(false, &vec);
- }
- Err(_) => {
- err_unrec(format!("Couldn't install {}", pkg));
- }
- };
- }
-}
diff --git a/src/mods/help.rs b/src/mods/help.rs
deleted file mode 100644
index 5cd2bee..0000000
--- a/src/mods/help.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use crate::mods::strs::{err_rec, inf};
-
-pub fn help() {
- // print help message
- println!();
- inf("Usage:".to_string());
- println!(
- "
-ame -S(n) / ins - install a package
-ame -R(n) / rm - remove a package
-ame -Rs(n) / purge - remove a package with it dependencies
-ame -Syu(n) / 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 / ver - contributors and version info
-ame -h / help - display this help message
-
-ame - passes said flags to be processed by pacman"
- );
- println!();
- err_rec("Appending 'n' where (n) is present passes '--noconfirm' to pacman. Use at your own risk. (alternatively, using '--noconfirm' as a flag works too.)".to_string());
- println!();
-}
diff --git a/src/mods/inssort.rs b/src/mods/inssort.rs
deleted file mode 100644
index d24f97f..0000000
--- a/src/mods/inssort.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-use crate::{clone, err_unrec, install, mods::strs::sec, mods::rpc::*};
-use regex::Regex;
-use std::process::{Command, Stdio};
-
-pub fn inssort(noconfirm: bool, as_dep: bool, pkgs: Vec) {
- // TODO: understand what the fuck is actually going on here
- let mut repo = vec![];
- let mut aur = vec![];
- let re = Regex::new(r"(\S+)((?:>=|<=|>|<)\S+$)").unwrap();
- let reg = Regex::new(r"((?:>=|<=|>|<)\S+$)").unwrap();
- for pkg in pkgs {
- match pkg.contains('/') {
- true => match pkg.split('/').collect::>()[0] == "aur" {
- true => {
- aur.push(pkg.split('/').collect::>()[1].to_string());
- }
- false => {
- let out = Command::new("bash")
- .arg("-c")
- .arg(format!(
- "pacman -Sl {} | grep {}",
- pkg.split('/').collect::>()[0],
- pkg.split('/').collect::>()[1]
- ))
- .stdout(Stdio::null())
- .status()
- .expect("Something has gone wrong.");
- match out.code() {
- Some(0) => repo.push(reg.replace_all(&pkg, "").to_string()),
- Some(1) => err_unrec(format!(
- "Package {} not found in repository {}",
- pkg.split('/').collect::>()[1],
- pkg.split('/').collect::>()[0]
- )),
- Some(_) => err_unrec("Something has gone terribly wrong".to_string()),
- None => err_unrec("Process terminated".to_string()),
- }
- }
- },
- false => {
- let caps = re.captures(&pkg);
- match caps {
- Some(_) => {
- let out = Command::new("pacman")
- .arg("-Ss")
- .arg(format!(
- "^{}$",
- caps.unwrap().get(1).map_or("", |m| m.as_str())
- ))
- .stdout(Stdio::null())
- .status()
- .expect("Something has gone wrong.");
- match out.code() {
- Some(0) => repo.push(reg.replace_all(&pkg, "").to_string()),
- Some(1) => aur.push(pkg),
- Some(_) => err_unrec("Something has gone terribly wrong".to_string()),
- None => err_unrec("Process terminated".to_string()),
- }
- }
- None => {
- let out = Command::new("pacman")
- .arg("-Ss")
- .arg(format!("^{}$", &pkg))
- .stdout(Stdio::null())
- .status()
- .expect("Something has gone wrong.");
- match out.code() {
- Some(0) => repo.push(pkg),
- Some(1) => aur.push(pkg),
- Some(_) => err_unrec("Something has gone terribly wrong".to_string()),
- None => err_unrec("Process terminated".to_string()),
- }
- }
- }
- }
- }
- }
- if !as_dep {
- if !repo.is_empty() {
- sec(format!("Installing repo packages: {}", &repo.join(", ")));
- install(noconfirm, false, &repo.join(" "));
- }
-
- for a in aur {
- sec(format!("Couldn't find {} in repos. Searching AUR", a));
- let md = &rpcinfo(&a).make_depends;
- inssort(noconfirm, true, md.to_vec());
- clone(noconfirm, false, &a);
- }
- } else {
- if !repo.is_empty() {
- sec(format!("Installing repo packages: {}", &repo.join(", ")));
- install(noconfirm, true, &repo.join(" "));
- }
-
- for a in aur {
- sec(format!("Couldn't find {} in repos. Searching AUR", a));
- let md = &rpcinfo(&a).make_depends;
- inssort(noconfirm, true, md.to_vec());
- clone(noconfirm, true, &a);
- }
- }
-}
-
-pub fn inssort_from_file(noconfirm: bool, as_dep: bool, file: &str) {
- // same thing as above but with a list of packages from a file
- let mut pkgs: Vec = Vec::new();
- let contents = std::fs::read_to_string(&file).expect("Couldn't read file");
- for line in contents.lines() {
- pkgs.push(line.to_string());
- }
- let mut repo = vec![];
- let mut aur = vec![];
- let re = Regex::new(r"(\S+)((?:>=|<=)\S+$)").unwrap();
- let reg = Regex::new(r"((?:>=|<=)\S+$)").unwrap();
- for pkg in pkgs {
- match pkg.contains('/') {
- true => match pkg.split('/').collect::>()[0] == "aur" {
- true => {
- aur.push(pkg.split('/').collect::>()[1].to_string());
- }
- false => {
- let out = Command::new("bash")
- .arg("-c")
- .arg(format!(
- "pacman -Sl {} | grep {}",
- pkg.split('/').collect::>()[0],
- pkg.split('/').collect::>()[1]
- ))
- .stdout(Stdio::null())
- .status()
- .expect("Something has gone wrong.");
- match out.code() {
- Some(0) => repo.push(reg.replace_all(&pkg, "").to_string()),
- Some(1) => err_unrec(format!(
- "Package {} not found in repository {}",
- pkg.split('/').collect::>()[1],
- pkg.split('/').collect::>()[0]
- )),
- Some(_) => err_unrec("Something has gone terribly wrong".to_string()),
- None => err_unrec("Process terminated".to_string()),
- }
- }
- },
- false => {
- let caps = re.captures(&pkg);
- match caps {
- Some(_) => {
- let out = Command::new("pacman")
- .arg("-Ss")
- .arg(format!(
- "^{}$",
- caps.unwrap().get(1).map_or("", |m| m.as_str())
- ))
- .stdout(Stdio::null())
- .status()
- .expect("Something has gone wrong.");
- match out.code() {
- Some(0) => repo.push(reg.replace_all(&pkg, "").to_string()),
- Some(1) => aur.push(pkg),
- Some(_) => err_unrec("Something has gone terribly wrong".to_string()),
- None => err_unrec("Process terminated".to_string()),
- }
- }
- None => {
- let out = Command::new("pacman")
- .arg("-Ss")
- .arg(format!("^{}$", &pkg))
- .stdout(Stdio::null())
- .status()
- .expect("Something has gone wrong.");
- match out.code() {
- Some(0) => repo.push(pkg),
- Some(1) => aur.push(pkg),
- Some(_) => err_unrec("Something has gone terribly wrong".to_string()),
- None => err_unrec("Process terminated".to_string()),
- }
- }
- }
- }
- }
- }
- if !as_dep {
- if !repo.is_empty() {
- sec(format!("Installing repo packages: {}", &repo.join(", ")));
- install(noconfirm, false, &repo.join(" "));
- }
-
- for a in aur {
- sec(format!("Couldn't find {} in repos. Searching AUR", a));
- let md = &rpcinfo(&a).make_depends;
- inssort(noconfirm, true, md.to_vec());
- clone(noconfirm, false, &a);
- }
- } else {
- if !repo.is_empty() {
- sec(format!("Installing repo packages: {}", &repo.join(", ")));
- install(noconfirm, true, &repo.join(" "));
- }
-
- for a in aur {
- sec(format!("Couldn't find {} in repos. Searching AUR", a));
- let md = &rpcinfo(&a).make_depends;
- inssort(noconfirm, true, md.to_vec());
- clone(noconfirm, true, &a);
- }
- }
-}
diff --git a/src/mods/install.rs b/src/mods/install.rs
deleted file mode 100644
index 2c13edf..0000000
--- a/src/mods/install.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use crate::mods::database::add_pkg;
-use crate::mods::strs::{err_unrec, succ};
-use runas::Command;
-
-pub fn install(noconfirm: bool, as_dep: bool, pkg: &str) {
- // install a package
- let pkgs: Vec<&str> = pkg.split(' ').collect();
- if !as_dep {
- if noconfirm {
- let result = Command::new("pacman")
- .arg("-S")
- .arg("--noconfirm")
- .arg("--needed")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!("Succesfully installed packages: {}", pkg));
- add_pkg(true, &pkgs);
- }
- Some(_) => err_unrec(format!("Couldn't install packages: {}", pkg)),
- None => err_unrec(format!("Couldn't install packages: {}", pkg)),
- };
- } else {
- let result = Command::new("pacman")
- .arg("-S")
- .arg("--needed")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!("Succesfully installed packages: {}", pkg));
- add_pkg(true, &pkgs);
- }
- Some(_) => err_unrec(format!("Couldn't install packages: {}", pkg)),
- None => err_unrec(format!("Couldn't install packages: {}", pkg)),
- };
- }
- } else {
- let result = Command::new("pacman")
- .arg("-S")
- .arg("--noconfirm")
- .arg("--needed")
- .arg("--asdeps")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!("Succesfully installed packages: {}", pkg));
- add_pkg(true, &pkgs);
- }
- Some(_) => err_unrec(format!("Couldn't install packages: {}", pkg)),
- None => err_unrec(format!("Couldn't install packages: {}", pkg)),
- };
- }
-}
diff --git a/src/mods/purge.rs b/src/mods/purge.rs
deleted file mode 100644
index 6879507..0000000
--- a/src/mods/purge.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-use crate::mods::{
- database::rem_pkg,
- strs::{err_rec, err_unrec, sec, succ},
-};
-use runas::Command;
-use std::{fs, path::Path};
-
-pub fn purge(noconfirm: bool, pkgs: Vec) {
- // purge packages
- sec(format!(
- "Attempting to uninstall packages: {}",
- &pkgs.join(" ")
- ));
- if noconfirm {
- let result = Command::new("pacman")
- .arg("-Rsu")
- .args(&pkgs)
- .arg("--noconfirm")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- } else {
- let result = Command::new("pacman")
- .arg("-Rsu")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- }
- for pkg in &pkgs {
- let pkgdir = format!("{}/.cache/ame/{}", std::env::var("HOME").unwrap(), pkg);
- let path = Path::new(&pkgdir);
- if path.is_dir() {
- let rm_result = fs::remove_dir_all(&path);
- match rm_result {
- Ok(_) => succ(format!("Removed AUR cache directory for {}", pkg)),
- Err(_) => err_unrec(format!("Failed to remove AUR cache directory for {}", pkg)),
- };
- }
- }
-}
-
-pub fn purge_from_file(noconfirm: bool, file: &str) {
- // purge packages from list of packages
- let mut pkgs: Vec = Vec::new();
- let contents = std::fs::read_to_string(&file).expect("Couldn't read file");
- for line in contents.lines() {
- pkgs.push(line.to_string());
- }
- sec(format!(
- "Attempting to uninstall packages: {}",
- &pkgs.join(" ")
- ));
- if noconfirm {
- let result = Command::new("pacman")
- .arg("-Rsu")
- .args(&pkgs)
- .arg("--noconfirm")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- } else {
- let result = Command::new("pacman")
- .arg("-Rsu")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- }
- for pkg in &pkgs {
- let pkgdir = format!("{}/.cache/ame/{}", std::env::var("HOME").unwrap(), pkg);
- let path = Path::new(&pkgdir);
- if path.is_dir() {
- let rm_result = fs::remove_dir_all(&path);
- match rm_result {
- Ok(_) => succ(format!("Removed AUR cache directory for {}", pkg)),
- Err(_) => err_unrec(format!("Failed to remove AUR cache directory for {}", pkg)),
- };
- }
- }
-}
diff --git a/src/mods/rpc.rs b/src/mods/rpc.rs
deleted file mode 100644
index be9cc13..0000000
--- a/src/mods/rpc.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-#[derive(serde::Deserialize, Debug, Clone)]
-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().results[0].clone()
-}
-
-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()
-}
diff --git a/src/mods/search.rs b/src/mods/search.rs
deleted file mode 100644
index f3c0e31..0000000
--- a/src/mods/search.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::mods::rpc::*;
-use crate::mods::strs::{err_rec, err_unrec, succ};
-use ansi_term::Colour;
-use std::process::Command;
-
-pub fn a_search(pkg: &str) {
- // search for a package in the AUR
- let results = rpcsearch(pkg).results;
-
- for r in &results {
- if results.is_empty() {
- err_rec("No matching AUR packages found".to_string());
- }
- 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());
- }
-}
-
-pub fn r_search(pkg: &str) {
- // search for a package in the repositories
- let result = Command::new("pacman")
- .arg("-Ss")
- .arg(&pkg)
- .status()
- .unwrap();
- match result.code() {
- Some(0) => succ("Repo search successful".to_string()),
- Some(1) => err_rec("No matching repo packages found".to_string()),
- Some(_) => err_unrec("Someting went terribly wrong".to_string()),
- None => err_unrec("Couldn't search pacman repos".to_string()),
- };
-}
diff --git a/src/mods/stat_database.rs b/src/mods/stat_database.rs
deleted file mode 100644
index cec1b91..0000000
--- a/src/mods/stat_database.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-use crate::{err_unrec, inf};
-use std::env;
-
-pub fn stat_dump_dat() -> Vec {
- 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() {
- dat_pkgs.push(value.unwrap().to_string());
- }
- true
- });
- match result {
- Ok(_) => {
- //inf("Dumped static packages".to_string());
- }
- Err(_) => err_unrec("Couldn't dump packages from database".to_string()),
- }
- 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;
- match sear_value {
- "name" => {
- let result = connection.iterate(
- format!("SELECT name FROM static_pkgs WHERE name = \"{}\";", &pkg),
- |pairs| {
- for &(_column, _value) in pairs.iter() {
- return_val = true;
- }
- return_val
- },
- );
- match result {
- Ok(_) => {}
- Err(_) => err_unrec("Couldn't get value from database".to_string()),
- }
- return return_val;
- }
- "update" => {
- let result = connection.iterate(
- format!("SELECT pin FROM static_pkgs WHERE name = \"{}\";", &pkg),
- |pairs| {
- for &(_column, _value) in pairs.iter() {
- return_val = true;
- }
- return_val
- },
- );
- match result {
- Ok(_) => {}
- Err(_) => err_unrec("Couldn't get value from database".to_string()),
- }
- return return_val;
- }
- _ => return_val = false,
- }
- return_val
-}
-
-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);
- for i in static_pkgs {
- let result = connection.execute(format!(
- "
- DELETE FROM static_pkgs WHERE name = \"{}\";
- ",
- i
- ));
- match result {
- Ok(_) => inf(format!("Removed {} from database", i)),
- Err(_) => err_unrec(format!(
- "Couldn't remove {} from database (static packages table)",
- i
- )),
- }
- }
-}
-
-pub fn stat_add_pkg(update: &str, pkg: &str) {
- let file = format!("{}/.local/share/ame/aur_pkgs.db", env::var("HOME").unwrap());
- let connection = sqlite::open(file).unwrap();
- let pin = if update == "true" { 1 } else { 0 };
- let result = connection.execute(format!(
- "
- INSERT INTO static_pkgs (name, pin) VALUES (\"{}\", {});
- ",
- pkg, pin
- ));
- match result {
- Ok(_) => inf(format!("Added {} to database", pkg)),
- Err(_) => err_unrec(format!("Couldn't add {} to database", pkg)),
- }
-}
diff --git a/src/mods/statpkgs.rs b/src/mods/statpkgs.rs
deleted file mode 100644
index 50db5b5..0000000
--- a/src/mods/statpkgs.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use crate::inf;
-use crate::{
- err_rec, inssort, stat_add_pkg, stat_dump_dat, stat_get_value, stat_rem_pkg, uninstall,
-};
-use std::{env, fs};
-
-pub fn rebuild(noconfirm: bool) {
- let file = format!("{}/.config/ame/pkgs.toml", env::var("HOME").unwrap());
- 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();
- 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 = ", ""));
- tempvec.push(key.to_string());
- tempvec.push(format!("{}", value).replace("update = ", ""));
- pkgs.push(tempvec);
- }
- }
- let mut pkgs_to_add: Vec> = Vec::new();
- let mut pkgs_to_install: Vec = Vec::new();
- for i in pkgs {
- if !stat_get_value(&i[0], "name") {
- 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.is_empty() {
- inf(format!("Installing {}", pkgs_to_install.join(", ")));
- inssort(noconfirm, false, pkgs_to_install);
- for i in pkgs_to_add {
- stat_add_pkg(&i[1], &i[0]);
- }
- config_no_change += 1;
- }
- let dat_pkgs = stat_dump_dat();
-
- let mut pkgs = Vec::new();
- if let Some(entry) = db_parsed.as_table() {
- for (key, _value) in &*entry {
- pkgs.push(key);
- }
- }
-
- let mut pkgs_to_remove: Vec = Vec::new();
- for i in dat_pkgs {
- if !pkgs.contains(&&i) {
- pkgs_to_remove.push(i.to_string());
- }
- config_no_change += 1;
- }
- if !pkgs_to_remove.is_empty() {
- inf(format!("Removing {}", pkgs_to_remove.join(", ")));
- stat_rem_pkg(&pkgs_to_remove);
- uninstall(noconfirm, pkgs_to_remove);
- }
-
- if config_no_change != 0 {
- inf("Rebuild Complete".to_string());
- } else {
- err_rec("Configuration not changed!".to_string());
- }
-}
diff --git a/src/mods/strs.rs b/src/mods/strs.rs
deleted file mode 100644
index 6cc5e50..0000000
--- a/src/mods/strs.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-use ansi_term::Colour;
-use std::{env, io, io::Write, process, string};
-use uwuizer::*;
-
-pub fn inf(a: string::String) {
- // info
- if env::var("AME_UWU").unwrap_or_else(|_| "n/a".to_string()) == "YES" {
- println!(
- "{} {}",
- Colour::Purple.paint("❖"),
- Colour::White.paint(uwuize!(&a))
- );
- } else {
- println!("{} {}", Colour::Purple.paint("❖"), Colour::White.paint(a));
- }
-}
-
-pub fn sec(a: string::String) {
- if env::var("AME_UWU").unwrap_or_else(|_| "n/a".to_string()) == "YES" {
- println!(
- "{} {}",
- Colour::Purple.bold().paint("❖"),
- Colour::White.bold().paint(uwuize!(&a))
- );
- } else {
- println!(
- "{} {}",
- Colour::Purple.bold().paint("❖"),
- Colour::White.bold().paint(a)
- );
- }
-}
-
-pub fn succ(a: string::String) {
- // success
- if env::var("AME_UWU").unwrap_or_else(|_| "n/a".to_string()) == "YES" {
- println!(
- "{} {}",
- Colour::Green.bold().paint("✓"),
- Colour::Green.paint(uwuize!(&a))
- );
- } else {
- println!(
- "{} {}",
- Colour::Green.bold().paint("✓"),
- Colour::Green.paint(&a)
- );
- }
-}
-
-pub fn prompt(a: string::String) -> bool {
- // prompt
- if env::var("AME_UWU").unwrap_or_else(|_| "n/a".to_string()) == "YES" {
- print!(
- "{} {} {}",
- Colour::Purple.bold().paint("❖"),
- Colour::White.bold().paint(uwuize!(&a)),
- Colour::White.bold().paint("(Y/n): ")
- );
- } else {
- print!(
- "{} {} {}",
- Colour::Purple.bold().paint("❖"),
- Colour::White.bold().paint(&a),
- Colour::White.bold().paint("(Y/n): ")
- );
- }
- io::stdout().flush().ok();
- let mut yn: String = String::new();
- let _ = std::io::stdin().read_line(&mut yn);
- !(yn.trim() == "n" || yn.trim() == "N" || yn.trim() == "no" || yn.trim() == "No")
-}
-
-pub fn err_unrec(a: string::String) {
- // unrecoverable error
- if env::var("AME_UWU").unwrap_or_else(|_| "n/a".to_string()) == "YES" {
- println!(
- "{} {} {}",
- Colour::Red.bold().paint(uwuize!("✖ Unrecoverable error:")),
- Colour::Red.paint(uwuize!(&a)),
- Colour::Red.bold().paint(uwuize!("Terminating."))
- );
- } else {
- println!(
- "{} {} {}",
- Colour::Red.bold().paint("✖ Unrecoverable error:"),
- Colour::Red.paint(a),
- Colour::Red.bold().paint("Terminating.")
- );
- }
- process::exit(1);
-}
-
-pub fn err_rec(a: string::String) {
- // recoverable error
- if env::var("AME_UWU").unwrap_or_else(|_| "n/a".to_string()) == "YES" {
- println!(
- "{} {}",
- Colour::Yellow.bold().paint(uwuize!("⚠ WARNING:")),
- Colour::Yellow.paint(uwuize!(&a))
- );
- } else {
- println!(
- "{} {}",
- Colour::Yellow.bold().paint("⚠ WARNING:"),
- Colour::Yellow.paint(a)
- );
- }
-}
diff --git a/src/mods/uninstall.rs b/src/mods/uninstall.rs
deleted file mode 100644
index 6b04845..0000000
--- a/src/mods/uninstall.rs
+++ /dev/null
@@ -1,160 +0,0 @@
-use crate::mods::{
- database::rem_pkg,
- strs::{err_rec, err_unrec, sec, succ},
-};
-use runas::Command;
-use std::{fs, path::Path};
-
-pub fn uninstall(noconfirm: bool, pkgs: Vec) {
- // uninstall a package
- sec(format!(
- "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());
- }
- }
- }
- if !matches.is_empty() {
- 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")
- .args(&pkgs)
- .arg("--noconfirm")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- } else {
- let result = Command::new("pacman")
- .arg("-Ru")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- }
- for pkg in &pkgs {
- let pkgdir = format!("{}/.cache/ame/{}", std::env::var("HOME").unwrap(), pkg);
- let path = Path::new(&pkgdir);
- if path.is_dir() {
- let rm_result = fs::remove_dir_all(&path);
- match rm_result {
- Ok(_) => succ(format!("Removed AUR cache directory for {}", pkg)),
- Err(_) => err_unrec(format!("Failed to remove AUR cache directory for {}", pkg)),
- };
- }
- }
-}
-
-pub fn uninstall_from_file(noconfirm: bool, file: &str) {
- // uninstall a package from a list of packages
- let mut pkgs: Vec = Vec::new();
- let contents = std::fs::read_to_string(&file).expect("Couldn't read file");
- for line in contents.lines() {
- pkgs.push(line.to_string());
- }
- sec(format!(
- "Attempting to uninstall packages: {}",
- &pkgs.join(" ")
- ));
- if noconfirm {
- let result = Command::new("pacman")
- .arg("-Ru")
- .args(&pkgs)
- .arg("--noconfirm")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- } else {
- let result = Command::new("pacman")
- .arg("-Ru")
- .args(&pkgs)
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => {
- succ(format!(
- "Succesfully uninstalled packages: {}",
- &pkgs.join(" ")
- ));
- rem_pkg(&pkgs);
- }
- Some(_) => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- None => err_rec(format!("Couldn't uninstall packages: {}", &pkgs.join(" "))),
- };
- }
- for pkg in &pkgs {
- let pkgdir = format!("{}/.cache/ame/{}", std::env::var("HOME").unwrap(), pkg);
- let path = Path::new(&pkgdir);
- if path.is_dir() {
- let rm_result = fs::remove_dir_all(&path);
- match rm_result {
- Ok(_) => succ(format!("Removed AUR cache directory for {}", pkg)),
- Err(_) => err_unrec(format!("Failed to remove AUR cache directory for {}", pkg)),
- };
- }
- }
-}
diff --git a/src/mods/update.rs b/src/mods/update.rs
deleted file mode 100644
index 8b76034..0000000
--- a/src/mods/update.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use crate::mods::strs::{err_unrec, sec, succ};
-use runas::Command;
-
-pub fn update() {
- // update the repositories
- sec("Syncing package repos".to_string());
-
- let result = Command::new("pacman")
- .arg("-Sy")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => succ("Repos succesfully synced".to_string()),
- Some(_) => err_unrec("Couldn't sync package repos".to_string()),
- None => err_unrec("Couldn't sync package repos".to_string()),
- }
-}
diff --git a/src/mods/upgrade.rs b/src/mods/upgrade.rs
deleted file mode 100644
index 7fdf94f..0000000
--- a/src/mods/upgrade.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-use crate::{
- err_rec, err_unrec, inf, inssort, mods::database::get_value, mods::rpc::*, mods::strs::prompt,
- mods::strs::sec, mods::strs::succ, uninstall,
-};
-use runas::Command;
-use std::{env, fs, path::Path};
-use toml;
-
-fn uninstall_make_depend(pkg: &str) {
- // uninstall make depends installed by ame itself
- let make_depends = rpcinfo(pkg).make_depends;
-
- if !make_depends.is_empty() {
- inf(format!(
- "{} installed following make dependencies: {}",
- pkg,
- make_depends.join(", ")
- ));
- let remove = prompt("Would you like to remove them?".to_string());
- if remove {
- uninstall(true, make_depends);
- }
- }
- succ(format!("Succesfully upgraded {}", pkg));
-}
-
-pub fn upgrade(noconfirm: bool) {
- // upgrade all packages
- let homepath = env::var("HOME").unwrap();
- let cachedir = format!("/{}/.cache/ame/", homepath);
- let cache_exists = Path::new(&format!("/{}/.cache/ame/", homepath)).is_dir();
- let file = format!("{}/.local/ame/aurPkgs.db", env::var("HOME").unwrap());
- let database = String::new();
- if Path::new(&file).exists() {
- let _db = fs::read_to_string(&file).expect("Can't Open Database");
- } else {
- let _cdar = fs::create_dir_all(format!("/{}/.local/ame/", homepath));
- match _cdar {
- Ok(_) => inf("Created cache directory (previously missing)".to_string()),
- Err(_) => err_unrec("Couldn't create cache directory".to_string()),
- }
- err_rec(String::from("Database wasn't found, creating new one"));
- let _dbfile = fs::File::create(&file);
- let _db = String::new();
- }
- let db_parsed = database.parse::().expect("Invalid Database");
-
- if !cache_exists {
- let cachecreate = fs::create_dir_all(&cachedir);
- match cachecreate {
- Ok(_) => inf("Creating cachedir. (didn't exist previously)".to_string()),
- Err(_) => err_unrec("Couldn't create cachedir".to_string()),
- }
- }
- sec("Performing system upgrade".to_string());
- if noconfirm {
- let result = Command::new("pacman")
- .arg("-Syu")
- .arg("--noconfirm")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => succ("All repo packages upgraded".to_string()),
- Some(_) => err_unrec("Couldn't upgrade packages".to_string()),
- None => err_unrec("Couldn't upgrade packages".to_string()),
- };
- } else {
- let result = Command::new("pacman")
- .arg("-Syu")
- .status()
- .expect("Couldn't call pacman");
- match result.code() {
- Some(0) => succ("All repo packages upgraded".to_string()),
- Some(_) => err_unrec("Couldn't upgrade packages".to_string()),
- None => err_unrec("Couldn't upgrade packages".to_string()),
- };
- }
-
- if let Some(entry) = db_parsed.as_table() {
- for (key, _value) in &*entry {
- let results = rpcsearch(&key.to_string()).results;
- let url = format!("https://aur.archlinux.org/{}.git", key);
- let package = rpcinfo(&key.to_string());
- let version = get_value(key, "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);
- match cd_result {
- Ok(_) => inf("Entered package directory".to_string()),
- Err(_) => err_unrec("Could not enter package directory".to_string()),
- }
- inssort(true, true, package.depends.clone());
-
- sec(format!("Installing {} ...", &key));
- let install_result = std::process::Command::new("makepkg")
- .arg("-si")
- .arg("--noconfirm")
- .arg("--needed")
- .status();
- match install_result {
- Ok(_) => {
- uninstall_make_depend(key);
- }
- Err(_) => {
- err_unrec(format!("Couldn't install {}", &key));
- }
- };
-
- sec(format!("Installing {} ...", &key));
- let install_result = std::process::Command::new("makepkg")
- .arg("-si")
- .arg("--needed")
- .status()
- .expect("Couldn't call makepkg");
- match install_result.code() {
- Some(0) => {
- uninstall_make_depend(key);
- }
- Some(_) => {
- err_unrec(format!("Couldn't install {}", &key));
- }
- None => {
- err_unrec(format!("Couldn't install {}", &key));
- }
- };
- } else {
- inf(format!("Cloning {} ...", &key));
-
- if Path::new(&keydir).is_dir() {
- let rm_result = fs::remove_dir_all(&keydir);
- match rm_result {
- Ok(_) => inf(format!(
- "Package path for {} already found. Removing to reinstall",
- &key
- )),
- Err(_) => err_unrec(format!(
- "Package path for {} already found, but could not remove to reinstall",
- &key
- )),
- }
- }
-
- let dir_result = fs::create_dir(&keydir);
- match dir_result {
- Ok(_) => inf(format!("Created package directory for {}", &key)),
- Err(_) => {
- err_unrec(format!("Couldn't create package directory for {}", &key))
- }
- }
-
- let cd_result = env::set_current_dir(&keydir);
- match cd_result {
- Ok(_) => inf("Entered package directory".to_string()),
- Err(_) => err_unrec("Could not enter package directory".to_string()),
- }
-
- inssort(true, true, package.depends.clone());
-
- let clone = std::process::Command::new("git")
- .arg("clone")
- .arg(&url)
- .arg(&keydir)
- .status()
- .expect("Couldn't clone repo");
- match clone.code() {
- Some(0) => {
- inf(format!("Cloning {} into package directory", &key));
- }
- Some(_) => {
- err_unrec(format!("Failed cloning {} into package directory", &key))
- }
- _ => err_unrec(format!("Failed cloning {} into package directory", &key)),
- }
- }
-
- sec(format!("Installing {} ...", &key));
- let install_result = std::process::Command::new("makepkg")
- .arg("-si")
- .arg("--noconfirm")
- .arg("--needed")
- .status();
- match install_result {
- Ok(_) => {
- uninstall_make_depend(key);
- }
- Err(_) => {
- err_unrec(format!("Couldn't install {}", &key));
- }
- };
- sec(format!("Installing {} ...", &key));
- let install_result = std::process::Command::new("makepkg")
- .arg("-si")
- .arg("--needed")
- .status()
- .expect("Couldn't call makepkg");
- match install_result.code() {
- Some(0) => {
- uninstall_make_depend(key);
- }
- Some(_) => {
- err_unrec(format!("Couldn't install {}", &key));
- }
- None => {
- err_unrec(format!("Couldn't install {}", &key));
- }
- };
- } else {
- inf(format!("Package {} already up to date", &key));
- }
- }
- }
-}
diff --git a/src/mods/ver.rs b/src/mods/ver.rs
deleted file mode 100644
index 251802d..0000000
--- a/src/mods/ver.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use crate::inf;
-use ansi_term::Colour;
-
-pub fn ver() {
- const VERSION: &str = env!("CARGO_PKG_VERSION");
-
- // print version and contributors
- println!();
- inf(format!("ame - {}", VERSION));
- println!();
- inf("Contributors:".to_string());
- println!("- axtlos ");
- println!("- jnats ");
- println!("- jasio ");
- println!("- generic ");
- println!();
- inf("This software is licensed under the BSD 3-Clause license.".to_string());
- inf("All source code is available at:".to_string());
- println!();
- println!(
- "{}",
- Colour::Purple
- .bold()
- .paint("https://git.getcryst.al/crystal/ame")
- );
- println!();
-}
diff --git a/src/mods/xargs.rs b/src/mods/xargs.rs
deleted file mode 100644
index 4728659..0000000
--- a/src/mods/xargs.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-pub fn noconf(args: &[String]) -> bool {
- // noconfirm if user passed --noconfirm or added n to the end of the arg
- args.contains(&"--noconfirm".to_string()) || args[0].ends_with(&"n".to_string())
-}
-
-pub fn argssort(args: &mut Vec) -> &Vec {
- // sort the args
- if args.contains(&"--noconfirm".to_string()) {
- args.retain(|x| x != &"--noconfirm".to_string());
- return args;
- }
- args
-}
diff --git a/src/operations/aur_install.rs b/src/operations/aur_install.rs
new file mode 100644
index 0000000..4a8533e
--- /dev/null
+++ b/src/operations/aur_install.rs
@@ -0,0 +1,145 @@
+use std::env;
+use std::env::set_current_dir;
+use std::fs::remove_dir_all;
+use std::path::Path;
+use std::process::{Command, Stdio};
+
+use crate::{info, log, Options};
+use crate::internal::{crash, prompt};
+use crate::internal::rpc::rpcinfo;
+
+pub fn aur_install(a: Vec, options: Options) {
+ let url = crate::internal::rpc::URL;
+ let cachedir = format!("{}/.cache/ame/", env::var("HOME").unwrap());
+ let verbosity = options.verbosity;
+ let noconfirm = options.noconfirm;
+
+ if verbosity >= 1 {
+ log(format!("Installing from AUR: {:?}", &a));
+ }
+
+ info(format!("Installing packages {} from the AUR", a.join(", ")));
+
+ for package in a {
+ let rpcres = rpcinfo(package);
+
+ if !rpcres.found {
+ break;
+ }
+
+ let pkg = &rpcres.package.as_ref().unwrap().name;
+
+ if verbosity >= 1 {
+ log(format!("Cloning {} into cachedir", pkg));
+ }
+
+ info("Cloning package source".to_string());
+
+ set_current_dir(Path::new(&cachedir)).unwrap();
+ Command::new("git")
+ .arg("clone")
+ .arg(format!("{}/{}", url, pkg))
+ .stdout(Stdio::null())
+ .status()
+ .expect("Something has gone wrong");
+
+ if verbosity >= 1 {
+ log(format!(
+ "Cloned {} into cachedir, moving on to resolving dependencies",
+ pkg
+ ));
+ log(format!(
+ "Raw dependencies for package {} are:\n{:?}",
+ pkg,
+ rpcres.package.as_ref().unwrap().depends.join(", ")
+ ));
+ }
+
+ // dep sorting
+ info("Sorting dependencies".to_string());
+ let sorted = crate::internal::sort(&rpcres.package.as_ref().unwrap().depends, options);
+
+ if verbosity >= 1 {
+ log(format!(
+ "Sorted dependencies for {} are:\n{:?}",
+ pkg, &sorted
+ ));
+ }
+
+ let newopts = Options {
+ verbosity,
+ noconfirm,
+ asdeps: true,
+ };
+
+ if !sorted.nf.is_empty() {
+ crash(
+ format!(
+ "Could not find dependencies {} for package {}, aborting",
+ sorted.nf.join(", "),
+ pkg
+ ),
+ 5,
+ );
+ }
+
+ if !noconfirm {
+ let p1 = prompt(
+ format!("Would you like to review {}'s PKGBUILD?", pkg),
+ false,
+ );
+ let editor = env::var("PAGER").unwrap_or_else(|_| "less".parse().unwrap());
+
+ if p1 {
+ Command::new(editor)
+ .arg(format!("{}/PKGBUILD", pkg))
+ .spawn()
+ .unwrap()
+ .wait()
+ .unwrap();
+ let p2 = prompt(format!("Would you still like to install {}?", pkg), true);
+ if !p2 {
+ crash("Not proceeding".to_string(), 6);
+ }
+ }
+ }
+
+ // dep installing
+ info("Moving on to install dependencies".to_string());
+ if !sorted.repo.is_empty() {
+ crate::operations::install(sorted.repo, newopts);
+ }
+ if !sorted.aur.is_empty() {
+ crate::operations::aur_install(sorted.aur, newopts);
+ }
+
+ let mut makepkg_args = vec!["-rsic", "--needed"];
+ if options.asdeps {
+ makepkg_args.push("--asdeps")
+ }
+ if options.noconfirm {
+ makepkg_args.push("--noconfirm")
+ }
+
+ // package building and installing
+ info("Building time!".to_string());
+ set_current_dir(format!("{}/{}", cachedir, pkg)).unwrap();
+ let out = Command::new("makepkg")
+ .args(&makepkg_args)
+ .status()
+ .expect("Something has gone wrong");
+
+ if out.code() != Some(0) {
+ crash(
+ format!("Error encountered while installing {}, aborting", pkg),
+ 7,
+ );
+ }
+
+ set_current_dir(&cachedir).unwrap();
+ remove_dir_all(format!("{}/{}", cachedir, &pkg)).unwrap();
+
+ // pushes package to database
+ crate::database::add(rpcres.package.unwrap(), options);
+ }
+}
diff --git a/src/operations/install.rs b/src/operations/install.rs
new file mode 100644
index 0000000..95f1ddf
--- /dev/null
+++ b/src/operations/install.rs
@@ -0,0 +1,38 @@
+use crate::{crash, info, log, Options};
+
+pub fn install(a: Vec, options: Options) {
+ info(format!("Installing packages {} from repos", &a.join(", ")));
+ let mut opers = vec![];
+ if options.noconfirm {
+ opers.push("--noconfirm".to_string());
+ }
+ if options.asdeps {
+ opers.push("--asdeps".to_string());
+ }
+ let verbosity = options.verbosity;
+ if verbosity >= 1 {
+ log(format!("Installing from repos: {:?}", &a));
+ }
+
+ let r = runas::Command::new("pacman")
+ .arg("-S")
+ .arg("--needed")
+ .args(&a)
+ .args(&opers)
+ .status()
+ .expect("Something has gone wrong");
+
+ if r.code() != Some(0) {
+ crash(
+ format!(
+ "An error occured while installing packages: {}, aborting",
+ a.join(", ")
+ ),
+ 7,
+ );
+ }
+
+ if verbosity >= 1 {
+ log(format!("Installing packages: {:?} was successful", &a));
+ }
+}
diff --git a/src/operations/mod.rs b/src/operations/mod.rs
new file mode 100644
index 0000000..cb6f241
--- /dev/null
+++ b/src/operations/mod.rs
@@ -0,0 +1,31 @@
+use crate::Options;
+
+mod aur_install;
+mod install;
+mod search;
+mod uninstall;
+mod upgrade;
+
+pub fn install(a: Vec, options: Options) {
+ install::install(a, options);
+}
+
+pub fn uninstall(a: Vec, options: Options) {
+ uninstall::uninstall(a, options);
+}
+
+pub fn search(a: &str, options: Options) {
+ search::repo_search(a, options);
+}
+
+pub fn aur_install(a: Vec, options: Options) {
+ aur_install::aur_install(a, options);
+}
+
+pub fn aur_search(a: &str, options: Options) {
+ search::aur_search(a, options);
+}
+
+pub fn upgrade(options: Options) {
+ upgrade::upgrade(options);
+}
diff --git a/src/operations/search.rs b/src/operations/search.rs
new file mode 100644
index 0000000..053d9fd
--- /dev/null
+++ b/src/operations/search.rs
@@ -0,0 +1,48 @@
+use std::process::Command;
+
+use crate::{log, Options};
+use crate::internal::rpc::rpcsearch;
+
+pub fn aur_search(a: &str, options: Options) {
+ let verbosity = options.verbosity;
+ let res = rpcsearch(a.to_string());
+
+ if verbosity >= 1 {
+ log(format!(
+ "Found {} resuls for \"{}\" in AUR",
+ res.resultcount, a
+ ));
+ }
+
+ for r in &res.results {
+ println!(
+ "aur/{} {}\n {}",
+ r.name,
+ r.version,
+ r.description
+ .as_ref()
+ .unwrap_or(&"No description".to_string())
+ )
+ }
+}
+
+pub fn repo_search(a: &str, options: Options) {
+ let verbosity = options.verbosity;
+ let rs = Command::new("pacman")
+ .arg("-Ss")
+ .arg(format!("^{}$", &a))
+ .output()
+ .expect("Something has gone wrong");
+
+ let str = String::from_utf8(rs.stdout).unwrap();
+
+ if verbosity >= 1 {
+ log(format!(
+ "Found {} results for \"{}\" in repos",
+ &str.split('\n').count() / 2,
+ &a
+ ));
+ }
+
+ print!("{}", str);
+}
diff --git a/src/operations/uninstall.rs b/src/operations/uninstall.rs
new file mode 100644
index 0000000..208943d
--- /dev/null
+++ b/src/operations/uninstall.rs
@@ -0,0 +1,45 @@
+use std::{env, fs};
+use std::path::Path;
+
+use crate::{log, Options};
+
+pub fn uninstall(mut a: Vec, options: Options) {
+ let b = a.clone();
+ if options.noconfirm {
+ a.push("--noconfirm".to_string());
+ }
+ let verbosity = options.verbosity;
+ if verbosity >= 1 {
+ log(format!("Uninstalling: {:?}", &b));
+ }
+
+ let r = runas::Command::new("pacman")
+ .arg("-Rs")
+ .args(&a)
+ .status()
+ .expect("Something has gone wrong");
+
+ if let Some(x) = r.code() {
+ if verbosity >= 1 {
+ log(format!(
+ "Uninstalling packages: {:?} exited with code {}",
+ &b, x
+ ));
+ }
+ }
+
+ for b in a {
+ crate::database::remove(&b, options);
+ if Path::new(&format!("{}/.cache/ame/{}", env::var("HOME").unwrap(), b)).exists() {
+ if verbosity >= 1 {
+ log("Old cache directory found, deleting".to_string());
+ }
+ fs::remove_dir_all(Path::new(&format!(
+ "{}/.cache/ame/{}",
+ env::var("HOME").unwrap(),
+ b
+ )))
+ .unwrap();
+ }
+ }
+}
diff --git a/src/operations/upgrade.rs b/src/operations/upgrade.rs
new file mode 100644
index 0000000..1a761a0
--- /dev/null
+++ b/src/operations/upgrade.rs
@@ -0,0 +1,49 @@
+use runas::Command;
+
+use crate::{info, log, Options};
+use crate::internal::rpc::rpcinfo;
+use crate::operations::aur_install::aur_install;
+
+pub fn upgrade(options: Options) {
+ let verbosity = options.verbosity;
+ let noconfirm = options.noconfirm;
+
+ let mut pacman_args = vec!["-Syu"];
+ if noconfirm {
+ pacman_args.push("--noconfirm");
+ }
+
+ if verbosity >= 1 {
+ log("Upgrading repo packages".to_string());
+ }
+
+ Command::new("pacman")
+ .args(&pacman_args)
+ .status()
+ .expect("Something has gone wrong");
+
+ if verbosity >= 1 {
+ log("Upgrading AUR packages".to_string());
+ }
+
+ let res = crate::database::query(options);
+
+ if verbosity >= 1 {
+ log(format!("{:?}", &res));
+ }
+
+ let mut aur_upgrades = vec![];
+ for r in res {
+ let re = r.clone();
+ let ver = rpcinfo(r.name);
+ if ver.package.unwrap().version != r.version {
+ aur_upgrades.push(re.name);
+ }
+ }
+
+ if !aur_upgrades.is_empty() {
+ aur_install(aur_upgrades, options);
+ } else {
+ info("No upgrades available for installed AUR packages".to_string());
+ }
+}