Lotsss of comments

i18n
Michal 2 years ago
parent 68a13e58ed
commit 21f958d0fe
No known key found for this signature in database
GPG Key ID: A6A1A4DCB22279B9

2
.gitignore vendored

@ -1,6 +1,4 @@
target/
ame
ame.exe
.vscode
.idea
result

@ -1,27 +0,0 @@
image: "rust:latest"
default:
before_script:
- rustc --version
- cargo --version
stages:
- test
lint-code:
stage: test
script:
- rustup component add clippy
- cargo clippy -- -D warnings
format-code:
stage: test
script:
- rustup component add rustfmt
- cargo fmt -- --check
audit-code:
stage: test
script:
- cargo install cargo-audit
- cargo audit

@ -1,28 +0,0 @@
# 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

@ -7,39 +7,6 @@ description = "A fast and efficient AUR helper"
license-file = "LICENSE.md"
default-run = "ame"
[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"
path = "src/main.rs"

@ -1,8 +1,31 @@
{
"nodes": {
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1658730563,
"narHash": "sha256-NDaSjaNdynCM02hRLOL76CKeD5Bxjxe8aNsD6AQ4U5I=",
"owner": "nix-community",
"repo": "fenix",
"rev": "80981ee71b32ce0747d22b1fd2dcd895219f5c1d",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs"
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1655042882,
@ -20,40 +43,45 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1656755932,
"narHash": "sha256-TGThfOxr+HjFK464+UoUE6rClp2cwxjiKvHcBVdIGSQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "660ac43ff9ab1f12e28bfb31d4719795777fe152",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1656945861,
"narHash": "sha256-L41+pANwxKvhqqGRCKXzugOb81ewFJG95esLobRI1KY=",
"lastModified": 1658644204,
"narHash": "sha256-MWyfCH9K3eVTXJUxBi67OQSAh9jJAnvWklM6qm4j8w8=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "4d26010c93091d4cb7fca36b8d3ecb33c89a6f23",
"rev": "2f0c3be57c348f4cfd8820f2d189e29a685d9c41",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"fenix": "fenix",
"naersk": "naersk",
"nixpkgs": "nixpkgs_2",
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1658671895,
"narHash": "sha256-WFtdMN7WH5twFZEfBqpgc9PMCMHpgJnZyipDSPfui3U=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "7e2b983fd459977e11026683ee4afb9598960a4c",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
"utils": {
"locked": {
"lastModified": 1656928814,

@ -1,46 +1,89 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs";
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
utils.url = "github:numtide/flake-utils";
naersk.url = "github:nix-community/naersk";
naersk = {
url = "github:nix-community/naersk";
inputs.nixpkgs.follows = "nixpkgs";
};
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, utils, naersk }:
utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages."${system}";
naersk-lib = naersk.lib."${system}";
in rec
{
packages.amethyst = naersk-lib.buildPackage {
pname = "ame";
root = ./.;
nativeBuildInputs = with pkgs; [
openssl
sqlite
pkg-config
];
};
packages.default = packages.amethyst;
apps.amethyst = utils.lib.mkApp {
drv = packages.amethyst;
};
apps.default = apps.amethyst;
devShells.default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
rustc
cargo
rustfmt
cargo-audit
clippy
openssl
sqlite
pkg-config
];
};
});
outputs = {
self,
nixpkgs,
utils,
naersk,
fenix,
}:
utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages."${system}";
toolchain = with fenix.packages."${system}";
combine [
minimal.rustc
minimal.cargo
targets.x86_64-pc-windows-gnu.latest.rust-std
targets.x86_64-unknown-linux-gnu.latest.rust-std
];
naersk-lib = naersk.lib."${system}".override {
cargo = toolchain;
rustc = toolchain;
};
in rec
{
packages.amethyst = naersk-lib.buildPackage {
pname = "Amethyst";
root = ./.;
};
packages.amethyst-win = naersk-lib.buildPackage {
pname = "Amethyst";
root = ./.;
strictDeps = true;
depsBuildBuild = with pkgs; [
pkgsCross.mingwW64.stdenv.cc
pkgsCross.mingwW64.windows.pthreads
];
nativeBuildInputs = with pkgs; [
(
if system == "x86_64-linux"
then wineWowPackages.stable
else hello
)
];
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = pkgs.writeScript "wine-wrapper" ''
export WINEPREFIX="$(mktemp -d)"
exec wine64 $@
'';
doCheck = true;
};
packages.default = packages.amethyst;
apps.apod = utils.lib.mkApp {
drv = packages.amethyst;
};
apps.default = apps.amethyst;
devShells.default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
rustc
cargo
cargo-audit
rustfmt
clippy
openssl
sqlite
pkg-config
];
};
formatter = pkgs.alejandra;
});
}

@ -57,6 +57,12 @@ pub struct InstallArgs {
/// The name of the package(s) to install
#[clap(required = true)]
pub packages: Vec<String>,
/// Installs only from the AUR
pub aur: bool,
/// Install the packages from the pacman-defined repositories
pub repo: bool,
}
#[derive(Default, Debug, Clone, Parser)]

@ -1,14 +0,0 @@
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);
}

@ -1,14 +0,0 @@
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);
}

@ -1,14 +0,0 @@
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);
}

@ -1,14 +0,0 @@
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);
}

@ -1,14 +0,0 @@
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);
}

@ -1,14 +0,0 @@
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);
}

@ -5,11 +5,15 @@ use crate::{crash, log, Options};
use super::get_database_connection;
pub fn add(pkg: Package, options: Options) {
// Initialise database connection
let conn = get_database_connection();
// Log the package name
if options.verbosity >= 1 {
log!("Adding package {} to database", pkg.name);
}
// Push the package to the database
let pkg_description = pkg
.description
.unwrap_or_else(|| "No description found.".parse().unwrap());

@ -6,21 +6,24 @@ use crate::internal::exit_code::AppExitCode;
use crate::{crash, log, Options};
pub fn init(options: Options) {
// Initialise variables
let path = format!("{}/.local/share/ame/db.sqlite", env::var("HOME").unwrap());
let dbpath = Path::new(&path);
let verbosity = options.verbosity;
// Log database path
if verbosity >= 1 {
log!("Creating database at {}", &path);
}
// Initialise database connection
let conn =
Connection::open(dbpath).expect("Couldn't create database at ~/.local/share/ame/db.sqlite");
if verbosity >= 1 {
log!("Populating database with table");
}
// Create table
conn.execute(
"CREATE TABLE packages (
name TEXT PRIMARY KEY NOT NULL,

@ -6,12 +6,14 @@ use crate::internal::rpc::Package;
use crate::{log, Options};
pub fn query(options: Options) -> Vec<Package> {
// Initialise variables
let verbosity = options.verbosity;
if verbosity >= 1 {
log!("Connecting to database");
}
// Initialise database connection
let conn = Connection::open(Path::new(&format!(
"{}/.local/share/ame/db.sqlite",
env::var("HOME").unwrap()
@ -22,6 +24,7 @@ pub fn query(options: Options) -> Vec<Package> {
log!("Querying database for input");
}
// Get all database contents
let mut rs = conn.prepare("SELECT * FROM packages;").unwrap();
let packages_iter = rs
.query_map([], |row| {
@ -49,8 +52,8 @@ pub fn query(options: Options) -> Vec<Package> {
log!("Retrieved results");
}
// Convert to vector
let mut results: Vec<Package> = vec![];
for package in packages_iter {
results.push(package.unwrap());
}

@ -3,14 +3,17 @@ use crate::{log, Options};
use super::get_database_connection;
pub fn remove(pkg: &str, options: Options) {
// Initialise database connection
let conn = get_database_connection();
// Initialise variables
let verbosity = options.verbosity;
if verbosity >= 1 {
log!("Removing package {} from database", pkg);
}
// Remove the package from the database
conn.execute(
"DELETE FROM packages
WHERE EXISTS

@ -3,10 +3,12 @@ use regex::Regex;
use crate::{log, Options};
pub fn clean(a: &[String], options: Options) -> Vec<String> {
// Strip versioning from package names
let r = Regex::new(r"(\S+)((?:>=|<=|>|<)\S+$)").unwrap();
let mut cleaned: Vec<String> = vec![];
let verbosity = options.verbosity;
// Push cleaned package names to vector
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());

@ -6,15 +6,18 @@ use crate::{prompt, warn};
pub fn detect() {
let mut pacnew = vec![];
// Detect pacnew files
for entry in std::fs::read_dir("/etc").unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.to_str().unwrap().contains(".pacnew") || path.to_str().unwrap().contains(".pacsave")
{
// If found, push to vector
pacnew.push(path);
}
}
// If pacnew files are found, warn the user and prompt to pacdiff
if !pacnew.is_empty() {
let choice = prompt!(default false, "It appears that at least one program you have installed / upgraded has installed a .pacnew/.pacsave config file. Would you like to run pacdiff to deal with this? You can always deal with this later by running `sudo pacdiff`");
if choice {

@ -5,9 +5,11 @@ use std::process::Command;
use crate::{crash, internal::exit_code::AppExitCode, log, Options};
pub fn init(options: Options) {
// Initialise variables
let verbosity = options.verbosity;
let homedir = env::var("HOME").unwrap();
// Initialise database path
if !Path::new(&format!("{}/.local/share/ame", homedir)).exists() {
let r = std::fs::create_dir_all(format!("{}/.local/share/ame", homedir));
match r {
@ -27,10 +29,12 @@ pub fn init(options: Options) {
}
}
// If database doesn't exist, create it
if !Path::new(&format!("{}/.local/share/ame/db.sqlite", homedir)).exists() {
crate::database::init(options);
}
// If cache path doesn't exist, create it, if it does, delete it and recreate it
if !Path::new(&format!("{}/.cache/ame/", homedir)).exists() {
let r = std::fs::create_dir_all(format!("{}/.cache/ame", homedir));
match r {
@ -83,6 +87,7 @@ pub fn init(options: Options) {
}
}
// Ensure proper permissions on cache path
let r = Command::new("chmod")
.arg("-R")
.arg("770")
@ -103,6 +108,8 @@ pub fn init(options: Options) {
);
}
};
// Ensure proper permissions on database path
let r = Command::new("chmod")
.arg("-R")
.arg("770")

@ -31,10 +31,15 @@ pub struct InfoResults {
pub const URL: &str = "https://aur.archlinux.org/";
pub fn rpcinfo(pkg: String) -> InfoResults {
// Initialise TLS connector
let tls_connector = Arc::new(native_tls::TlsConnector::new().unwrap());
// Build request agent
let agent = ureq::AgentBuilder::new()
.tls_connector(tls_connector)
.build();
// Send request and parse results into json
let res: SearchResults = agent
.get(&format!(
"https://aur.archlinux.org/rpc/?v=5&type=info&arg={}",
@ -45,6 +50,7 @@ pub fn rpcinfo(pkg: String) -> InfoResults {
.into_json()
.unwrap();
// Check if package was found
if res.results.is_empty() {
InfoResults {
found: false,
@ -59,10 +65,15 @@ pub fn rpcinfo(pkg: String) -> InfoResults {
}
pub fn rpcsearch(pkg: String) -> SearchResults {
// Initialise TLS connector
let tls_connector = Arc::new(native_tls::TlsConnector::new().unwrap());
// Build request agent
let agent = ureq::AgentBuilder::new()
.tls_connector(tls_connector)
.build();
// Send request and parse results into json
agent
.get(&format!(
"https://aur.archlinux.org/rpc/?v=5&type=search&arg={}",

@ -4,11 +4,13 @@ use crate::internal::{clean, rpc, structs};
use crate::{log, Options};
pub fn sort(input: &[String], options: Options) -> structs::Sorted {
// Initialise variables
let mut repo: Vec<String> = vec![];
let mut aur: Vec<String> = vec![];
let mut nf: Vec<String> = vec![];
let verbosity = options.verbosity;
// Sanitise all packages passed in
let a = clean(input, options);
if verbosity >= 1 {
@ -16,6 +18,7 @@ pub fn sort(input: &[String], options: Options) -> structs::Sorted {
}
for b in a {
// Check if package is in the repos
let rs = Command::new("pacman")
.arg("-Ss")
.arg(format!("^{}$", &b))
@ -24,16 +27,19 @@ pub fn sort(input: &[String], options: Options) -> structs::Sorted {
.expect("Something has gone wrong");
if let Some(0) = rs.code() {
// If it is, add it to the repo vector
if verbosity >= 1 {
log!("{} found in repos", b);
}
repo.push(b.to_string());
} else if rpc::rpcinfo(b.to_string()).found {
// Otherwise, check if it is in the AUR, if it is, add it to the AUR vector
if verbosity >= 1 {
log!("{} found in AUR", b);
}
aur.push(b.to_string());
} else {
// Otherwise, add it to the not found vector
if verbosity >= 1 {
log!("{} not found", b);
}

@ -17,27 +17,34 @@ mod internal;
mod operations;
fn main() {
// Break if we are running as root
if unsafe { libc::geteuid() } == 0 {
crash!( AppExitCode::RunAsRoot, "Running amethyst as root is disallowed as it can lead to system breakage. Instead, amethyst will prompt you when it needs superuser permissions");
}
// Parse arguments
let args: Args = Args::parse();
// Initialize variables
let verbosity = args.verbose as i32;
let noconfirm = args.no_confirm;
// Get options struct
let options = Options {
verbosity,
noconfirm,
asdeps: false,
};
// Ensure amethyst is initialized
init(options);
// Start sudoloop if specified
if args.sudoloop {
start_sudoloop();
}
// Match args
match args.subcommand.unwrap_or_default() {
Operation::Install(install_args) => cmd_install(install_args, options),
Operation::Remove(remove_args) => cmd_remove(remove_args, options),
@ -53,64 +60,65 @@ fn main() {
}
}
// Check for .pacnew files
detect();
}
fn cmd_install(args: InstallArgs, options: Options) {
// Initialise variables
let packages = args.packages;
let sorted = sort(&packages, options);
info!("Attempting to install packages: {}", packages.join(", "));
if !sorted.repo.is_empty() {
// If repo packages found, install them
operations::install(sorted.repo, options);
}
if !sorted.aur.is_empty() {
// If AUR packages found, install them
operations::aur_install(sorted.aur, options);
}
if !sorted.nf.is_empty() {
// If some packages are not found, crash TODO: this check should happen first
crash!(
AppExitCode::PacmanError,
"Couldn't find packages: {} in repos or the AUR",
sorted.nf.join(", ")
);
}
let bash_output = ShellCommand::bash()
.arg("-c")
.arg("sudo find /etc -name *.pacnew")
.wait_with_output()
.silent_unwrap(AppExitCode::Other)
.stdout;
if !bash_output.is_empty() {
let pacnew_files = bash_output
.split_whitespace()
.collect::<Vec<&str>>()
.join(", ");
info!("You have .pacnew files in /etc ({pacnew_files}) that you haven't removed or acted upon, it is recommended you do that now" );
}
}
fn cmd_remove(args: RemoveArgs, options: Options) {
// Initialise variables
let packages = args.packages;
info!("Uninstalling packages: {}", &packages.join(", "));
// Remove packages
operations::uninstall(packages, options);
}
fn cmd_search(args: SearchArgs, options: Options) {
// Initialise variables
let query_string = args.search.join(" ");
if args.aur {
info!("Searching AUR for {}", &query_string);
// Search AUR
operations::aur_search(&query_string, options);
}
if args.repo {
info!("Searching repos for {}", &query_string);
// Search repos
operations::search(&query_string, options);
}
if !args.aur && !args.repo {
info!("Searching AUR and repos for {}", &query_string);
// If no search type specified, search both
operations::search(&query_string, options);
operations::aur_search(&query_string, options);
}
@ -118,18 +126,21 @@ fn cmd_search(args: SearchArgs, options: Options) {
fn cmd_query(args: QueryArgs) {
if args.aur {
// If AUR query, query AUR
ShellCommand::pacman()
.arg("-Qm")
.wait_success()
.silent_unwrap(AppExitCode::PacmanError);
}
if args.repo {
// If repo query, query repos
ShellCommand::pacman()
.arg("-Qn")
.wait_success()
.silent_unwrap(AppExitCode::PacmanError);
}
if !args.repo && !args.aur {
// If no query type specified, query both
ShellCommand::pacman()
.arg("-Qn")
.wait_success()

@ -11,6 +11,7 @@ use crate::internal::rpc::rpcinfo;
use crate::{crash, info, log, prompt, Options};
pub fn aur_install(a: Vec<String>, options: Options) {
// Initialise variables
let url = crate::internal::rpc::URL;
let cachedir = format!("{}/.cache/ame/", env::var("HOME").unwrap());
let verbosity = options.verbosity;
@ -23,12 +24,15 @@ pub fn aur_install(a: Vec<String>, options: Options) {
info!("Installing packages {} from the AUR", a.join(", "));
for package in a {
// Query AUR for package info
let rpcres = rpcinfo(package);
if !rpcres.found {
// If package isn't found, break
break;
}
// Get package name
let pkg = &rpcres.package.as_ref().unwrap().name;
if verbosity >= 1 {
@ -37,6 +41,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
info!("Cloning package source");
// Clone package into cachedir
set_current_dir(Path::new(&cachedir)).unwrap();
ShellCommand::git()
.arg("clone")
@ -61,7 +66,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
);
}
// dep sorting
// Sort dependencies and makedepends
log!("Sorting dependencies");
let sorted = crate::internal::sort(&rpcres.package.as_ref().unwrap().depends, options);
log!("Sorting make dependencies");
@ -73,12 +78,14 @@ pub fn aur_install(a: Vec<String>, options: Options) {
log!("Sorted makedepends for {} are:\n{:?}", pkg, &md_sorted);
}
// Create newopts struct for installing dependencies
let newopts = Options {
verbosity,
noconfirm,
asdeps: true,
};
// If dependencies are not found in AUR or repos, crash
if !sorted.nf.is_empty() || !md_sorted.nf.is_empty() {
crash!(
AppExitCode::MissingDeps,
@ -89,6 +96,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
}
if !noconfirm {
// Prompt user to view PKGBUILD
let p1 = prompt!(default false,
"Would you like to review {}'s PKGBUILD (and any .install files if present)?",
pkg
@ -96,6 +104,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
let editor: &str = &env::var("PAGER").unwrap_or_else(|_| "less".parse().unwrap());
if p1 {
// Open PKGBUILD in pager
Command::new(editor)
.arg(format!("{}/PKGBUILD", pkg))
.spawn()
@ -103,6 +112,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
.wait()
.unwrap();
// Check if any .install files are present
let status = ShellCommand::bash()
.arg("-c")
.arg(format!("ls {}/*.install &> /dev/null", pkg))
@ -110,6 +120,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
.silent_unwrap(AppExitCode::Other);
if status.success() {
// If so, open them too
ShellCommand::bash()
.arg("-c")
.arg(format!("{} {}/*.install", editor, pkg))
@ -117,17 +128,19 @@ pub fn aur_install(a: Vec<String>, options: Options) {
.silent_unwrap(AppExitCode::Other);
}
// Prompt user to continue
let p2 = prompt!(default true, "Would you still like to install {}?", pkg);
if !p2 {
// If not, crash
fs::remove_dir_all(format!("{}/{}", cachedir, pkg)).unwrap();
crash!(AppExitCode::UserCancellation, "Not proceeding");
}
}
}
// dep installing
info!("Moving on to install dependencies");
// Install dependencies and makedepends
if !sorted.repo.is_empty() {
crate::operations::install(sorted.repo, newopts);
crate::operations::install(md_sorted.repo, newopts);
@ -137,6 +150,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
crate::operations::aur_install(md_sorted.aur, newopts);
}
// Build makepkg args
let mut makepkg_args = vec!["-rsci", "--skippgp"];
if options.asdeps {
makepkg_args.push("--asdeps")
@ -145,8 +159,9 @@ pub fn aur_install(a: Vec<String>, options: Options) {
makepkg_args.push("--noconfirm")
}
// package building and installing
info!("Building time!");
// Enter cachedir and build package
set_current_dir(format!("{}/{}", cachedir, pkg)).unwrap();
let status = ShellCommand::makepkg()
.args(makepkg_args)
@ -154,6 +169,7 @@ pub fn aur_install(a: Vec<String>, options: Options) {
.silent_unwrap(AppExitCode::MakePkgError);
if !status.success() {
// If build failed, crash
fs::remove_dir_all(format!("{}/{}", cachedir, pkg)).unwrap();
crash!(
AppExitCode::PacmanError,
@ -162,10 +178,13 @@ pub fn aur_install(a: Vec<String>, options: Options) {
);
}
// Return to cachedir
set_current_dir(&cachedir).unwrap();
// Remove package from cache
remove_dir_all(format!("{}/{}", cachedir, &pkg)).unwrap();
// pushes package to database
// Pushes package to database
crate::database::add(rpcres.package.unwrap(), options);
}
}

@ -13,29 +13,35 @@ pub fn clean(options: Options) {
let verbosity = options.verbosity;
let noconfirm = options.noconfirm;
// Check for orphaned packages
let orphaned_packages = ShellCommand::pacman()
.arg("-Qdtq")
.wait_with_output()
.silent_unwrap(AppExitCode::PacmanError);
if orphaned_packages.stdout.as_str() == "" {
if orphaned_packages.stdout.as_str().is_empty() {
// If no orphaned packages found, do nothing
info!("No orphaned packages found");
} else {
// Prompt users whether to remove orphaned packages
info!(
"Removing orphans would uninstall the following packages: \n{}",
&orphaned_packages.stdout
);
let cont = prompt!(default false, "Continue?");
if !cont {
// If user doesn't want to continue, break
info!("Exiting");
std::process::exit(AppExitCode::PacmanError as i32);
}
// Build pacman args
let mut pacman_args = vec!["-Rns"];
if noconfirm {
pacman_args.push("--noconfirm");
}
// Collect orphaned packages into a vector
let orphaned_packages_vec = orphaned_packages.stdout.split('\n').collect::<Vec<&str>>();
for package in &orphaned_packages_vec {
if !package.is_empty() {
@ -47,6 +53,7 @@ pub fn clean(options: Options) {
log!("Removing orphans: {:?}", orphaned_packages_vec);
}
// Remove orphaned packages
let pacman_result = ShellCommand::pacman()
.elevated()
.args(pacman_args)
@ -54,23 +61,29 @@ pub fn clean(options: Options) {
.silent_unwrap(AppExitCode::PacmanError);
if pacman_result.success() {
// If pacman succeeded, notify user
info!("Successfully removed orphans");
} else {
// If pacman failed, crash
crash!(AppExitCode::PacmanError, "Failed to remove orphans",);
}
}
// Prompt the user whether to clear cache or not
let clear_cache = if !noconfirm {
prompt!(default false, "Also clear pacman's package cache?")
} else {
true
};
if clear_cache {
// Build pacman args
let mut pacman_args = vec!["-Sc"];
if noconfirm {
pacman_args.push("--noconfirm");
}
// Build paccache args
let mut paccache_args = vec!["-r"];
if noconfirm {
paccache_args.push("--noconfirm");
@ -80,6 +93,7 @@ pub fn clean(options: Options) {
log!("Clearing using `paccache -r`");
}
// Clear pacman's cache (keeping latest 3 versions of installed packages)
Command::new("sudo")
.arg("paccache")
.args(paccache_args)
@ -98,6 +112,7 @@ pub fn clean(options: Options) {
log!("Clearing using `pacman -Sc`");
}
// Clear pacman's cache (keeping only installed packages)
let pacman_result = ShellCommand::pacman()
.elevated()
.args(pacman_args)
@ -105,8 +120,10 @@ pub fn clean(options: Options) {
.silent_unwrap(AppExitCode::PacmanError);
if pacman_result.success() {
// If pacman succeeded, notify user
info!("Successfully cleared package cache");
} else {
// If pacman failed, crash
crash!(AppExitCode::PacmanError, "Failed to clear package cache",);
}
}

@ -5,6 +5,8 @@ use crate::{crash, info, log, Options};
pub fn install(packages: Vec<String>, options: Options) {
info!("Installing packages {} from repos", &packages.join(", "));
// Build pacman args
let mut opers = vec!["-S", "--needed"];
if options.noconfirm {
opers.push("--noconfirm");
@ -19,6 +21,7 @@ pub fn install(packages: Vec<String>, options: Options) {
log!("Installing from repos: {:?}", &packages);
}
// Install packages
let status = ShellCommand::pacman()
.elevated()
.args(opers)
@ -26,6 +29,7 @@ pub fn install(packages: Vec<String>, options: Options) {
.wait()
.silent_unwrap(AppExitCode::PacmanError);
if !status.success() {
// If pacman failed, crash
crash!(
AppExitCode::PacmanError,
"An error occured while installing packages: {}, aborting",

@ -5,9 +5,13 @@ use crate::internal::rpc::rpcsearch;
use crate::{log, Options};
pub fn aur_search(query: &str, options: Options) {
// Initialise variables
let verbosity = options.verbosity;
// Query AUR for package info
let res = rpcsearch(query.to_string());
// Format output
for package in &res.results {
println!(
"aur/{} {}\n {}",
@ -26,7 +30,10 @@ pub fn aur_search(query: &str, options: Options) {
}
pub fn repo_search(query: &str, options: Options) {
// Initialise variables
let verbosity = options.verbosity;
// Query pacman for package info
let output = ShellCommand::pacman()
.arg("-Ss")
.arg(query)

@ -7,9 +7,9 @@ use crate::internal::exit_code::AppExitCode;
use crate::{log, Options};
pub fn uninstall(packages: Vec<String>, options: Options) {
// Build pacman args
let mut pacman_args = vec!["-Rs"];
pacman_args.append(&mut packages.iter().map(|s| s.as_str()).collect());
if options.noconfirm {
pacman_args.push("--noconfirm");
}
@ -18,6 +18,7 @@ pub fn uninstall(packages: Vec<String>, options: Options) {
log!("Uninstalling: {:?}", &packages);
}
// Uninstall packages
ShellCommand::pacman()
.elevated()
.args(pacman_args)
@ -29,7 +30,10 @@ pub fn uninstall(packages: Vec<String>, options: Options) {
}
for package in packages {
// Remove package from database
crate::database::remove(&package, options);
// Remove old cache directory
if Path::new(&format!(
"{}/.cache/ame/{}",
env::var("HOME").unwrap(),

@ -6,9 +6,11 @@ use crate::operations::aur_install::aur_install;
use crate::{info, log, prompt, Options};
pub fn upgrade(options: Options) {
// Initialise variables
let verbosity = options.verbosity;
let noconfirm = options.noconfirm;
// Build pacman args
let mut pacman_args = vec!["-Syu"];
if noconfirm {
pacman_args.push("--noconfirm");
@ -18,6 +20,7 @@ pub fn upgrade(options: Options) {
log!("Upgrading repo packages");
}
// Upgrade repo packages
let pacman_result = ShellCommand::pacman()
.elevated()
.args(pacman_args)
@ -25,12 +28,15 @@ pub fn upgrade(options: Options) {
.silent_unwrap(AppExitCode::PacmanError);
if pacman_result.success() {
// If pacman was successful, notify user
info!("Successfully upgraded repo packages");
} else {
// Otherwise, prompt user whether to continue
let cont = prompt!(default false,
"Failed to upgrade repo packages, continue to upgrading AUR packages?",
);
if !cont {
// If user doesn't want to continue, break
info!("Exiting");
std::process::exit(AppExitCode::PacmanError as i32);
}
@ -40,21 +46,27 @@ pub fn upgrade(options: Options) {
log!("Upgrading AUR packages");
}
// Query database for AUR packages
let res = crate::database::query(options);
if verbosity >= 1 {
log!("{:?}", &res);
}
// Check if AUR package versions are the same as installed
let mut aur_upgrades = vec![];
for r in res {
// Query AUR
let re = r.clone();
let ver = rpcinfo(r.name);
// If versions differ, push to a vector
if ver.package.unwrap().version != r.version {
aur_upgrades.push(re.name);
}
}
// If vector isn't empty, install AUR packages from vector, effectively upgrading
if !aur_upgrades.is_empty() {
aur_install(aur_upgrades, options);
} else {

Loading…
Cancel
Save