Merge pull request 'rewrite' (#16) from rewrite into main
Reviewed-on: https://git.getcryst.al/crystal/ame/pulls/16i18n
commit
96cc77950e
@ -1,6 +1,6 @@
|
|||||||
target/
|
target/
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
ame
|
ame
|
||||||
|
ame.exe
|
||||||
.vscode
|
.vscode
|
||||||
aur_pkgs.db
|
.idea
|
||||||
test.sql
|
|
||||||
|
@ -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
|
@ -1,19 +1,60 @@
|
|||||||
[package]
|
[package]
|
||||||
|
name = "Amethyst"
|
||||||
|
version = "3.0.0"
|
||||||
|
authors = ["michal <michal@tar.black>", "axtlos <axtlos@tar.black>"]
|
||||||
|
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"
|
name = "ame"
|
||||||
version = "0.0.0"
|
path = "src/main.rs"
|
||||||
authors = [ "jnats <michal@tar.black>", "axtlos <axtlos@tar.black>" ]
|
|
||||||
edition = "2018"
|
|
||||||
description = "a fast and efficient aur helper."
|
|
||||||
|
|
||||||
# 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]
|
[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"
|
runas = "0.2.1"
|
||||||
ansi_term = "0.12.1"
|
rusqlite = { version = "0.26.3", default-features = false }
|
||||||
uwuizer = "0.2.1"
|
ureq = { version = "2.4.0", default-features = false, features = ["native-tls", "json"] }
|
||||||
moins = "0.5.0"
|
serde = { version = "1.0.90", default-features = false, features = ["derive", "serde_derive"] }
|
||||||
regex = { version = "1.5.4", default-features = false }
|
native-tls = "0.2.8"
|
||||||
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" ] }
|
|
@ -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.
|
@ -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
|
|
@ -0,0 +1,14 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let arg = &env::args().collect::<Vec<String>>()[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::<Vec<&str>>()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let arg = &env::args().collect::<Vec<String>>()[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::<Vec<&str>>()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let arg = &env::args().collect::<Vec<String>>()[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::<Vec<&str>>()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let arg = &env::args().collect::<Vec<String>>()[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::<Vec<&str>>()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let arg = &env::args().collect::<Vec<String>>()[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::<Vec<&str>>()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let arg = &env::args().collect::<Vec<String>>()[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::<Vec<&str>>()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
@ -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
|
||||||
|
});
|
||||||
|
}
|
@ -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
|
||||||
|
});
|
||||||
|
}
|
@ -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<Package> {
|
||||||
|
query::query(options)
|
||||||
|
}
|
@ -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<Package> {
|
||||||
|
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::<usize, String>(3)
|
||||||
|
.unwrap()
|
||||||
|
.split(' ')
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<String>>(),
|
||||||
|
make_depends: row
|
||||||
|
.get::<usize, String>(4)
|
||||||
|
.unwrap()
|
||||||
|
.split(' ')
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<String>>(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.expect("Couldn't query database for packages");
|
||||||
|
|
||||||
|
if verbosity >= 1 {
|
||||||
|
log("Retrieved results".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut results: Vec<Package> = vec![];
|
||||||
|
|
||||||
|
for package in packages_iter {
|
||||||
|
results.push(package.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if verbosity >= 1 {
|
||||||
|
log("Collected results".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
results
|
||||||
|
}
|
@ -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");
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use crate::internal::strings::log;
|
||||||
|
use crate::Options;
|
||||||
|
|
||||||
|
pub fn clean(a: &[String], options: Options) -> Vec<String> {
|
||||||
|
let r = Regex::new(r"(\S+)((?:>=|<=|>|<)\S+$)").unwrap();
|
||||||
|
let mut cleaned: Vec<String> = 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
|
||||||
|
}
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<String> {
|
||||||
|
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
|
||||||
|
}};
|
||||||
|
}
|
@ -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<String>,
|
||||||
|
#[serde(rename = "Depends")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub depends: Vec<String>,
|
||||||
|
#[serde(rename = "MakeDepends")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub make_depends: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct SearchResults {
|
||||||
|
pub resultcount: u32,
|
||||||
|
pub results: Vec<Package>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct InfoResults {
|
||||||
|
pub found: bool,
|
||||||
|
pub package: Option<Package>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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::<SearchResults>()
|
||||||
|
.unwrap()
|
||||||
|
}
|
@ -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<String> = vec![];
|
||||||
|
let mut aur: Vec<String> = vec![];
|
||||||
|
let mut nf: Vec<String> = 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)
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
pub struct Sorted {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub repo: Vec<String>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub aur: Vec<String>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub nf: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sorted {
|
||||||
|
pub fn new(repo: Vec<String>, aur: Vec<String>, nf: Vec<String>) -> Self {
|
||||||
|
let a: Sorted = Sorted { repo, aur, nf };
|
||||||
|
a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Options {
|
||||||
|
pub verbosity: i32,
|
||||||
|
pub noconfirm: bool,
|
||||||
|
pub asdeps: bool,
|
||||||
|
}
|
@ -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;
|
|
@ -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();
|
|
||||||
}
|
|
@ -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::<Vec<&str>>();
|
|
||||||
|
|
||||||
let mut rem_pkgs: Vec<String> = 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));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <pkg> - install a package
|
|
||||||
ame -R(n) / rm <pkg> - remove a package
|
|
||||||
ame -Rs(n) / purge <pkg> - remove a package with it dependencies
|
|
||||||
ame -Syu(n) / upg - upgrade all packages to latest version
|
|
||||||
ame -Ss / sea <pkg> - search for a package
|
|
||||||
ame -Sa / aursea <pkg> - search for a package in the aur
|
|
||||||
ame -Sr / repsea <pkg> - search for a package in the repos
|
|
||||||
ame -v / ver - contributors and version info
|
|
||||||
ame -h / help - display this help message
|
|
||||||
|
|
||||||
ame <any valid pacman flags> - 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!();
|
|
||||||
}
|
|
@ -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<String>) {
|
|
||||||
// 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::<Vec<&str>>()[0] == "aur" {
|
|
||||||
true => {
|
|
||||||
aur.push(pkg.split('/').collect::<Vec<&str>>()[1].to_string());
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
let out = Command::new("bash")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(format!(
|
|
||||||
"pacman -Sl {} | grep {}",
|
|
||||||
pkg.split('/').collect::<Vec<&str>>()[0],
|
|
||||||
pkg.split('/').collect::<Vec<&str>>()[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::<Vec<&str>>()[1],
|
|
||||||
pkg.split('/').collect::<Vec<&str>>()[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<String> = 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::<Vec<&str>>()[0] == "aur" {
|
|
||||||
true => {
|
|
||||||
aur.push(pkg.split('/').collect::<Vec<&str>>()[1].to_string());
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
let out = Command::new("bash")
|
|
||||||
.arg("-c")
|
|
||||||
.arg(format!(
|
|
||||||
"pacman -Sl {} | grep {}",
|
|
||||||
pkg.split('/').collect::<Vec<&str>>()[0],
|
|
||||||
pkg.split('/').collect::<Vec<&str>>()[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::<Vec<&str>>()[1],
|
|
||||||
pkg.split('/').collect::<Vec<&str>>()[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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<String>) {
|
|
||||||
// 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<String> = 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)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<String>,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "Depends")]
|
|
||||||
pub depends: Vec<String>,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "MakeDepends")]
|
|
||||||
pub make_depends: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
pub struct SearchResults {
|
|
||||||
pub resultcount: u32,
|
|
||||||
pub results: Vec<Package>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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::<SearchResults>().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()
|
|
||||||
}
|
|
@ -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()),
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
use crate::{err_unrec, inf};
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
pub fn stat_dump_dat() -> Vec<String> {
|
|
||||||
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)),
|
|
||||||
}
|
|
||||||
}
|
|
@ -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::<toml::Value>().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<String>> = Vec::new();
|
|
||||||
let mut pkgs_to_install: Vec<String> = 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<String> = 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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<String>) {
|
|
||||||
// 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<String> = 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<String> = 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<String> = 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)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()),
|
|
||||||
}
|
|
||||||
}
|
|
@ -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::<toml::Value>().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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <axtlos@tar.black>");
|
|
||||||
println!("- jnats <michal@tar.black>");
|
|
||||||
println!("- jasio <jasiobene@icloud.com>");
|
|
||||||
println!("- generic <mdc028@bucknell.edu>");
|
|
||||||
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!();
|
|
||||||
}
|
|
@ -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<String>) -> &Vec<String> {
|
|
||||||
// sort the args
|
|
||||||
if args.contains(&"--noconfirm".to_string()) {
|
|
||||||
args.retain(|x| x != &"--noconfirm".to_string());
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
args
|
|
||||||
}
|
|
@ -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<String>, 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
use crate::{crash, info, log, Options};
|
||||||
|
|
||||||
|
pub fn install(a: Vec<String>, 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));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
use crate::Options;
|
||||||
|
|
||||||
|
mod aur_install;
|
||||||
|
mod install;
|
||||||
|
mod search;
|
||||||
|
mod uninstall;
|
||||||
|
mod upgrade;
|
||||||
|
|
||||||
|
pub fn install(a: Vec<String>, options: Options) {
|
||||||
|
install::install(a, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uninstall(a: Vec<String>, options: Options) {
|
||||||
|
uninstall::uninstall(a, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn search(a: &str, options: Options) {
|
||||||
|
search::repo_search(a, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn aur_install(a: Vec<String>, 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);
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
use std::{env, fs};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::{log, Options};
|
||||||
|
|
||||||
|
pub fn uninstall(mut a: Vec<String>, 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue