Reimplement logging by utilizing the tracing crate

Signed-off-by: trivernis <trivernis@protonmail.com>
i18n
trivernis 2 years ago
parent f1bbb2626c
commit 052d176f4a
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

147
Cargo.lock generated

@ -13,13 +13,16 @@ dependencies = [
"color-eyre", "color-eyre",
"colored", "colored",
"crossterm", "crossterm",
"dialoguer",
"futures", "futures",
"indicatif",
"lazy_static",
"libc", "libc",
"native-tls", "native-tls",
"parking_lot",
"regex", "regex",
"rusqlite", "rusqlite",
"serde", "serde",
"spinoff",
"textwrap", "textwrap",
"tokio", "tokio",
"toml", "toml",
@ -257,6 +260,20 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "console"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"terminal_size",
"unicode-width",
"winapi",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.3" version = "0.9.3"
@ -298,6 +315,23 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "dialoguer"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1"
dependencies = [
"console",
"tempfile",
"zeroize",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.31" version = "0.8.31"
@ -338,6 +372,12 @@ dependencies = [
"instant", "instant",
] ]
[[package]]
name = "fixedbitset"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -625,6 +665,18 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "indicatif"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc42b206e70d86ec03285b123e65a5458c92027d1fb2ae3555878b8113b3ddf"
dependencies = [
"console",
"number_prefix",
"tokio",
"unicode-width",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -696,12 +748,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]] [[package]]
name = "matchers" name = "matchers"
version = "0.1.0" version = "0.1.0"
@ -768,6 +814,22 @@ dependencies = [
"tempfile", "tempfile",
] ]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "number_prefix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]] [[package]]
name = "object" name = "object"
version = "0.29.0" version = "0.29.0"
@ -856,10 +918,13 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
dependencies = [ dependencies = [
"backtrace",
"cfg-if", "cfg-if",
"libc", "libc",
"petgraph",
"redox_syscall", "redox_syscall",
"smallvec", "smallvec",
"thread-id",
"windows-sys", "windows-sys",
] ]
@ -869,6 +934,16 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "petgraph"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.9" version = "0.2.9"
@ -1030,12 +1105,6 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustversion"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.11" version = "1.0.11"
@ -1194,46 +1263,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "spinoff"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c139aa6a2b4ed01ef761dfd593eb5b02218dbf35a3a0f10940b72f5bfe70426"
dependencies = [
"colored",
"maplit",
"once_cell",
"strum",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.99" version = "1.0.99"
@ -1310,6 +1345,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "thread-id"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fdfe0627923f7411a43ec9ec9c39c3a9b4151be313e0922042581fb6c9b717f"
dependencies = [
"libc",
"redox_syscall",
"winapi",
]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.1.4" version = "1.1.4"
@ -1345,6 +1391,7 @@ dependencies = [
"libc", "libc",
"memchr", "memchr",
"mio", "mio",
"num_cpus",
"once_cell", "once_cell",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
@ -1738,3 +1785,9 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "zeroize"
version = "1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"

@ -39,12 +39,15 @@ futures = "0.3.23"
tracing = "0.1.36" tracing = "0.1.36"
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] } tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
textwrap = "0.15.0" textwrap = "0.15.0"
spinoff = "0.5.3"
crossterm = "0.25.0" crossterm = "0.25.0"
toml = "0.5.9" toml = "0.5.9"
clap_complete = "3.2.4" clap_complete = "3.2.4"
color-eyre = { version = "0.6.2", features = ["issue-url", "url"] } color-eyre = { version = "0.6.2", features = ["issue-url", "url"] }
indicatif = { version = "0.17.0", features = ["tokio"] }
lazy_static = "1.4.0"
parking_lot = { version = "0.12.1", features = ["deadlock_detection"] }
dialoguer = "0.10.2"
[dependencies.tokio] [dependencies.tokio]
version = "1.20.1" version = "1.20.1"
features = ["rt", "io-std", "io-util", "process", "time", "macros", "tracing", "fs"] features = ["rt", "rt-multi-thread", "io-std", "io-util", "process", "time", "macros", "tracing", "fs"]

@ -1,13 +1,10 @@
use regex::Regex; use regex::Regex;
use crate::{log, Options};
/// Strips packages from versioning and other extraneous information. /// Strips packages from versioning and other extraneous information.
pub fn clean(a: &[String], options: Options) -> Vec<String> { pub fn clean(a: &[String]) -> Vec<String> {
// Strip versioning from package names // Strip versioning from package names
let r = Regex::new(r"(\S+)((?:>=|<=|>|<|=\W)\S+$)").unwrap(); let r = Regex::new(r"(\S+)((?:>=|<=|>|<|=\W)\S+$)").unwrap();
let mut cleaned: Vec<String> = vec![]; let mut cleaned: Vec<String> = vec![];
let verbosity = options.verbosity;
// Push cleaned package names to vector // Push cleaned package names to vector
for b in a { for b in a {
@ -19,9 +16,7 @@ pub fn clean(a: &[String], options: Options) -> Vec<String> {
} }
} }
if verbosity >= 1 { tracing::debug!("Cleaned: {:?}\nInto: {:?}", a, cleaned);
log!("Cleaned: {:?}\nInto: {:?}", a, cleaned);
}
cleaned cleaned
} }

@ -2,12 +2,16 @@ use crate::internal::commands::ShellCommand;
use crate::internal::config; use crate::internal::config;
use crate::internal::error::SilentUnwrap; use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::{prompt, spinner, warn}; use crate::logging::get_logger;
use crate::prompt;
use super::prompt_sudo_single;
/// Searches the filesystem for .pacnew files and helps the user deal with them. /// Searches the filesystem for .pacnew files and helps the user deal with them.
pub async fn detect() { pub async fn detect() {
// Start spinner prompt_sudo_single().await.expect("Sudo prompt failed");
let sp = spinner!("Scanning for pacnew files"); let pb = get_logger().new_progress_spinner();
pb.set_message("Scanning for pacnew files");
let mut pacnew = vec![]; let mut pacnew = vec![];
@ -27,11 +31,13 @@ pub async fn detect() {
// If pacnew files are found, warn the user and prompt to pacdiff // If pacnew files are found, warn the user and prompt to pacdiff
if pacnew.is_empty() { if pacnew.is_empty() {
sp.stop_bold("No pacnew files found"); pb.finish_with_message("No pacnew files found");
get_logger().reset_output_type();
} else { } else {
sp.stop_bold("It appears that at least one program you have installed / upgraded has installed a .pacnew config file. These are created when you have modified a program's configuration, and a package upgrade could not automatically merge the new file."); pb.finish_with_message("It appears that at least one program you have installed / upgraded has installed a .pacnew config file. These are created when you have modified a program's configuration, and a package upgrade could not automatically merge the new file.");
get_logger().reset_output_type();
let choice = prompt!(default false, "Would you like Amethyst to run pacdiff to deal with this? You can always deal with this later by running `sudo pacdiff`"); let choice = prompt!(default no, "Would you like Amethyst to run pacdiff to deal with this? You can always deal with this later by running `sudo pacdiff`");
if choice { if choice {
let config = config::read(); let config = config::read();
if config.base.pacdiff_warn { if config.base.pacdiff_warn {
@ -41,9 +47,9 @@ pub async fn detect() {
.await .await
.silent_unwrap(AppExitCode::PacmanError); .silent_unwrap(AppExitCode::PacmanError);
} else { } else {
warn!("Pacdiff uses vimdiff by default to edit files for merging. You can focus panes by mousing over them and pressing left click, and scroll up and down using your mouse's scroll wheel (or the arrow keys). To exit vimdiff, press the following key combination: ESC, :qa!, ENTER"); tracing::warn!("Pacdiff uses vimdiff by default to edit files for merging. You can focus panes by mousing over them and pressing left click, and scroll up and down using your mouse's scroll wheel (or the arrow keys). To exit vimdiff, press the following key combination: ESC, :qa!, ENTER");
warn!("You can surpress this warning in the future by setting `pacdiff_warn` to \"false\" in ~/.config/ame/config.toml"); tracing::warn!("You can surpress this warning in the future by setting `pacdiff_warn` to \"false\" in ~/.config/ame/config.toml");
let cont = prompt!(default false, "Continue?"); let cont = prompt!(default no, "Continue?");
if cont { if cont {
ShellCommand::pacdiff() ShellCommand::pacdiff()
.elevated() .elevated()

@ -2,19 +2,16 @@ use std::env;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use crate::{crash, internal::exit_code::AppExitCode, log, Options}; use crate::{crash, internal::exit_code::AppExitCode};
pub fn init(options: Options) { pub fn init() {
let verbosity = options.verbosity;
let homedir = env::var("HOME").unwrap(); let homedir = env::var("HOME").unwrap();
if !Path::new(&format!("{}/.local/share/ame", homedir)).exists() { if !Path::new(&format!("{}/.local/share/ame", homedir)).exists() {
let r = std::fs::create_dir_all(format!("{}/.local/share/ame", homedir)); let r = std::fs::create_dir_all(format!("{}/.local/share/ame", homedir));
match r { match r {
Ok(_) => { Ok(_) => {
if verbosity >= 1 { tracing::debug!("Created path: {}/.local/share/ame", homedir);
log!("Created path: {}/.local/share/ame", homedir);
}
} }
Err(e) => { Err(e) => {
crash!( crash!(
@ -31,9 +28,7 @@ pub fn init(options: Options) {
let r = std::fs::create_dir_all(format!("{}/.cache/ame", homedir)); let r = std::fs::create_dir_all(format!("{}/.cache/ame", homedir));
match r { match r {
Ok(_) => { Ok(_) => {
if verbosity >= 1 { tracing::debug!("Created path: {}/.cache/ame", homedir);
log!("Created path: {}/.cache/ame", homedir);
}
} }
Err(e) => { Err(e) => {
crash!( crash!(
@ -48,9 +43,7 @@ pub fn init(options: Options) {
let r = std::fs::remove_dir_all(format!("{}/.cache/ame", homedir)); let r = std::fs::remove_dir_all(format!("{}/.cache/ame", homedir));
match r { match r {
Ok(_) => { Ok(_) => {
if verbosity >= 1 { tracing::debug!("Removing cache: {}/.cache/ame", homedir);
log!("Removing cache: {}/.cache/ame", homedir);
}
} }
Err(e) => { Err(e) => {
crash!( crash!(
@ -64,9 +57,7 @@ pub fn init(options: Options) {
let r2 = std::fs::create_dir_all(format!("{}/.cache/ame", homedir)); let r2 = std::fs::create_dir_all(format!("{}/.cache/ame", homedir));
match r2 { match r2 {
Ok(_) => { Ok(_) => {
if verbosity >= 1 { tracing::debug!("Created path: {}/.cache/ame", homedir);
log!("Created path: {}/.cache/ame", homedir);
}
} }
Err(e2) => { Err(e2) => {
crash!( crash!(
@ -86,9 +77,7 @@ pub fn init(options: Options) {
.status(); .status();
match r { match r {
Ok(_) => { Ok(_) => {
if verbosity >= 1 { tracing::debug!("Set correct permissions for path: {}/.cache/ame", homedir);
log!("Set correct permissions for path: {}/.cache/ame", homedir);
}
} }
Err(e) => { Err(e) => {
crash!( crash!(
@ -106,12 +95,10 @@ pub fn init(options: Options) {
.status(); .status();
match r { match r {
Ok(_) => { Ok(_) => {
if verbosity >= 1 { tracing::debug!(
log!( "Set correct permissions for path: {}/.local/share/ame",
"Set correct permissions for path: {}/.local/share/ame", homedir
homedir );
);
}
} }
Err(e) => { Err(e) => {
crash!( crash!(

@ -45,11 +45,6 @@ pub fn uwu_enabled() -> bool {
config.extra.uwu.unwrap_or(false) config.extra.uwu.unwrap_or(false)
} }
pub fn uwu_debug_enabled() -> bool {
let config = config::read();
config.extra.uwu_debug.unwrap_or(false)
}
/// Checks if we're running in a tty. If we do we can assume that /// Checks if we're running in a tty. If we do we can assume that
/// the output can safely be colorized. /// the output can safely be colorized.
pub fn is_tty() -> bool { pub fn is_tty() -> bool {

@ -1,7 +1,7 @@
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use crate::internal::{clean, rpc, structs}; use crate::internal::{clean, rpc, structs};
use crate::{log, Options}; use crate::Options;
use super::error::SilentUnwrap; use super::error::SilentUnwrap;
use super::exit_code::AppExitCode; use super::exit_code::AppExitCode;
@ -11,13 +11,10 @@ pub async fn sort(input: &[String], options: Options) -> structs::Sorted {
let mut repo_packages: Vec<String> = vec![]; let mut repo_packages: Vec<String> = vec![];
let mut aur_packages: Vec<String> = vec![]; let mut aur_packages: Vec<String> = vec![];
let mut missing_packages: Vec<String> = vec![]; let mut missing_packages: Vec<String> = vec![];
let verbosity = options.verbosity;
let packages = clean(input, options); let packages = clean(input);
if verbosity >= 1 { tracing::debug!("Sorting: {:?}", packages.join(" "));
log!("Sorting: {:?}", packages.join(" "));
}
for package in packages { for package in packages {
let rs = Command::new("pacman") let rs = Command::new("pacman")
@ -28,23 +25,17 @@ pub async fn sort(input: &[String], options: Options) -> structs::Sorted {
.expect("Something has gone wrong"); .expect("Something has gone wrong");
if let Some(0) = rs.code() { if let Some(0) = rs.code() {
if verbosity >= 1 { tracing::debug!("{} found in repos", package);
log!("{} found in repos", package);
}
repo_packages.push(package.to_string()); repo_packages.push(package.to_string());
} else if rpc::rpcinfo(&package) } else if rpc::rpcinfo(&package)
.await .await
.silent_unwrap(AppExitCode::RpcError) .silent_unwrap(AppExitCode::RpcError)
.is_some() .is_some()
{ {
if verbosity >= 1 { tracing::debug!("{} found in AUR", package);
log!("{} found in AUR", package);
}
aur_packages.push(package.to_string()); aur_packages.push(package.to_string());
} else { } else {
if verbosity >= 1 { tracing::debug!("{} not found", package);
log!("{} not found", package);
}
missing_packages.push(package.to_string()); missing_packages.push(package.to_string());
} }
} }

@ -18,7 +18,6 @@ impl Sorted {
#[derive(Clone, Debug, Copy)] #[derive(Clone, Debug, Copy)]
/// Options to be passed down to internal functions /// Options to be passed down to internal functions
pub struct Options { pub struct Options {
pub verbosity: usize,
pub noconfirm: bool, pub noconfirm: bool,
pub asdeps: bool, pub asdeps: bool,
} }

@ -2,6 +2,8 @@ use std::time::Duration;
use crate::ShellCommand; use crate::ShellCommand;
use super::error::AppResult;
/// Loop sudo so it doesn't time out /// Loop sudo so it doesn't time out
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
pub async fn start_sudoloop() { pub async fn start_sudoloop() {
@ -16,5 +18,10 @@ pub async fn start_sudoloop() {
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
async fn prompt_sudo() { async fn prompt_sudo() {
while ShellCommand::sudo().arg("-v").wait_success().await.is_err() {} while prompt_sudo_single().await.is_err() {}
}
#[tracing::instrument(level = "trace")]
pub async fn prompt_sudo_single() -> AppResult<()> {
ShellCommand::sudo().arg("-v").wait_success().await
} }

@ -1,36 +1,8 @@
use colored::Colorize;
use std::io;
use std::io::Write;
use std::process::exit; use std::process::exit;
use std::time::UNIX_EPOCH;
use textwrap::wrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::{internal, uwu}; use crate::logging::get_logger;
use crate::logging::handler::PromptDefault;
const OK_SYMBOL: &str = "❖";
const ERR_SYMBOL: &str = "X";
const WARN_SYMBOL: &str = "!";
const PROMPT_SYMBOL: &str = "?";
const PROMPT_YN_DEFAULT_TRUE: &str = "[Y/n]";
const PROMPT_YN_DEFAULT_FALSE: &str = "[y/N]";
#[macro_export]
/// Macro for printing a message to stdout.
macro_rules! info {
($($arg:tt)+) => {
$crate::internal::utils::log_info(format!($($arg)+))
}
}
#[macro_export]
/// Macro for printing a warning message non-destructively.
macro_rules! warn {
($($arg:tt)+) => {
$crate::internal::utils::log_warn(format!($($arg)+))
}
}
#[macro_export] #[macro_export]
/// Macro for printing a message and destructively exiting /// Macro for printing a message and destructively exiting
@ -40,179 +12,27 @@ macro_rules! crash {
} }
} }
#[macro_export]
/// Macro for logging to stderr
macro_rules! log {
($($arg:tt)+) => {
$crate::internal::utils::log_debug(format!($($arg)+))
}
}
#[macro_export] #[macro_export]
/// Macro for prompting the user with a yes/no question. /// Macro for prompting the user with a yes/no question.
macro_rules! prompt { macro_rules! prompt {
(default $default:expr, $($arg:tt)+) => { (default yes, $($arg:tt)+) => {
$crate::internal::utils::prompt_yn(format!($($arg)+), $default) $crate::internal::utils::prompt_yn(format!($($arg)+), $crate::logging::handler::PromptDefault::Yes)
}
}
#[macro_export]
/// Macro for creating a spinner.
macro_rules! spinner {
($($arg:tt)+) => {
$crate::internal::utils::spinner_fn(format!($($arg)+))
}
}
/// Print a formatted message to stdout.
pub fn log_info(msg: String) {
let msg = if internal::uwu_enabled() {
uwu!(&msg)
} else {
msg
}; };
(default no, $($arg:tt)+) => {
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2) $crate::internal::utils::prompt_yn(format!($($arg)+), $crate::logging::handler::PromptDefault::No)
.subsequent_indent(" ");
println!(
"{} {}",
OK_SYMBOL.purple(),
wrap(&msg, opts).join("\n").bold()
);
}
/// Print a non-destructive warning message
pub fn log_warn(msg: String) {
let msg = if internal::uwu_enabled() {
uwu!(&msg)
} else {
msg
}; };
(no default, $($arg:tt)+) => {
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2) $crate::internal::utils::prompt_yn(format!($($arg)+), $crate::logging::handler::PromptDefault::None)
.subsequent_indent(" "); }
println!(
"{} {}",
WARN_SYMBOL.yellow(),
wrap(&msg, opts).join("\n").yellow().bold()
);
} }
/// Logs a message and exits the program with the given exit code. /// Logs a message and exits the program with the given exit code.
pub fn log_and_crash(msg: String, exit_code: AppExitCode) -> ! { pub fn log_and_crash(msg: String, exit_code: AppExitCode) -> ! {
let msg = if internal::uwu_enabled() { tracing::error!(msg);
uwu!(&msg)
} else {
msg
};
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2)
.subsequent_indent(" ");
println!(
"{} {}",
ERR_SYMBOL.red().bold(),
wrap(&msg, opts).join("\n").red().bold()
);
exit(exit_code as i32); exit(exit_code as i32);
} }
/// Logs a message to stderr with timestamp
pub fn log_debug(msg: String) {
let msg = if internal::uwu_enabled() && internal::uwu_debug_enabled() {
uwu!(&msg)
} else {
msg
};
eprintln!(
"{} {}",
std::time::SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
msg
);
}
/// Prompts the user for a yes/no answer. /// Prompts the user for a yes/no answer.
pub fn prompt_yn(question: String, default_true: bool) -> bool { pub fn prompt_yn(question: String, prompt_default: PromptDefault) -> bool {
let yn_prompt = if default_true { get_logger().prompt(question, prompt_default)
PROMPT_YN_DEFAULT_TRUE
} else {
PROMPT_YN_DEFAULT_FALSE
};
let question = if internal::uwu_enabled() {
uwu!(&question)
} else {
question
};
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2)
.subsequent_indent(" ");
print!(
"{} {} {}: ",
PROMPT_SYMBOL.purple(),
wrap(&question, opts).join("\n").bold(),
yn_prompt
);
let mut yn: String = String::new();
io::stdout().flush().ok();
io::stdin().read_line(&mut yn).unwrap();
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 {
default_true
}
}
pub struct Spinner {
spinner: spinoff::Spinner,
}
impl Spinner {
pub fn stop_bold(self, text: &str) {
let text = if internal::uwu_enabled() {
uwu!(text)
} else {
text.to_string()
};
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2)
.subsequent_indent(" ");
let symbol = format!("{}", OK_SYMBOL.purple());
let text = format!("{}", wrap(&text, opts).join("\n").bold());
self.spinner.stop_and_persist(&symbol, &text);
}
}
/// Returns a spinner that can be used to display progress.
pub fn spinner_fn(text: String) -> Spinner {
let text = if internal::uwu_enabled() {
uwu!(&text)
} else {
text
};
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2)
.subsequent_indent(" ");
Spinner {
spinner: spinoff::Spinner::new(
spinoff::Spinners::Line,
format!("{}", wrap(&text, opts).join("\n").bold()),
spinoff::Color::Magenta,
),
}
} }

@ -0,0 +1,146 @@
use colored::Colorize;
use std::collections::HashMap;
use std::sync::Arc;
use tracing_subscriber::registry::LookupSpan;
use tracing::field::Visit;
use tracing::{span, Level, Metadata, Subscriber};
use tracing_subscriber::Layer;
use super::handler::LogHandler;
use super::Verbosity;
const ENABLED_MODULES: &[&str] = &["ame"];
pub struct AmeFormatLayer {
logger: Arc<LogHandler>,
}
impl AmeFormatLayer {
pub fn new(logger: Arc<LogHandler>) -> Self {
Self { logger }
}
fn is_level_loggable(&self, level: &Level) -> bool {
self.logger.is_loggable(Verbosity::from_level(level))
}
fn is_enabled(&self, metadata: &Metadata) -> bool {
let level = metadata.level();
if !self.is_level_loggable(level) {
false
} else if let Some(module_path) = metadata.module_path() {
ENABLED_MODULES.iter().any(|m| module_path.starts_with(m))
} else {
false
}
}
fn log(&self, msg: String, level: &Level) {
match Verbosity::from_level(level) {
Verbosity::Error => self.logger.log_error(msg),
Verbosity::Warning => self.logger.log_warning(msg),
Verbosity::Info => self.logger.log_info(msg),
Verbosity::Debug => self.logger.log_debug(msg),
Verbosity::Trace => self.logger.log_trace(msg),
}
}
}
impl<S: Subscriber + for<'a> LookupSpan<'a>> Layer<S> for AmeFormatLayer {
/// When entering a span
fn on_new_span(
&self,
attrs: &span::Attributes<'_>,
_id: &span::Id,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
let metadata = attrs.metadata();
if self.is_enabled(metadata) {
let mut visitor = ValueDebugStorage::default();
attrs.record(&mut visitor);
let fields: Vec<String> = visitor
.values
.into_iter()
.map(|(k, v)| format!("{k} = {v}"))
.collect();
let mut fields_str = fields.join("\n ");
if !fields_str.is_empty() {
fields_str = format!("\n {fields_str}");
}
if let Some(module) = metadata.module_path() {
self.log(
format!(
"{} {}::{} {}",
"ENTER".italic(),
module,
metadata.name(),
fields_str.dimmed()
),
metadata.level(),
)
} else {
self.log(
format!(
"{} {} {}",
"ENTER".italic(),
metadata.name(),
fields_str.dimmed()
),
metadata.level(),
)
}
}
}
fn on_exit(&self, id: &span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
let span = ctx.span(id).unwrap();
let metadata = span.metadata();
if self.is_enabled(metadata) {
if let Some(module) = metadata.module_path() {
self.log(
format!("{} {}::{}", "EXIT".italic(), module, metadata.name(),),
metadata.level(),
);
} else {
self.log(
format!("{} {}", "EXIT".italic(), metadata.name()),
metadata.level(),
);
}
}
}
fn on_event(
&self,
event: &tracing::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
let metadata = event.metadata();
if self.is_enabled(metadata) {
let mut visitor = ValueDebugStorage::default();
event.record(&mut visitor);
let mut values = visitor.values;
if let Some(msg) = values.remove("message") {
self.log(msg, metadata.level())
}
}
}
}
#[derive(Default)]
pub struct ValueDebugStorage {
pub values: HashMap<String, String>,
}
impl Visit for ValueDebugStorage {
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
self.values
.insert(field.name().to_string(), format!("{:?}", value));
}
}

@ -0,0 +1,177 @@
use colored::Colorize;
use indicatif::{MultiProgress, ProgressBar};
use std::{
sync::{atomic::AtomicBool, Arc},
time::Duration,
};
use crate::uwu;
use dialoguer::Confirm;
use super::Verbosity;
use parking_lot::RwLock;
const OK_SYMBOL: &str = "❖";
const ERR_SYMBOL: &str = "X";
const WARN_SYMBOL: &str = "!";
const DEBUG_SYMBOL: &str = "⌘";
const TRACE_SYMBOL: &str = "🗲";
const PROMPT_SYMBOL: &str = "?";
pub struct LogHandler {
level: Arc<RwLock<Verbosity>>,
output_type: Arc<RwLock<OutputType>>,
uwu_enabled: Arc<AtomicBool>,
}
impl Default for LogHandler {
fn default() -> Self {
Self {
level: Arc::new(RwLock::new(Verbosity::Info)),
output_type: Arc::new(RwLock::new(OutputType::Stderr)),
uwu_enabled: Arc::new(AtomicBool::new(false)),
}
}
}
#[allow(unused)]
pub enum OutputType {
Stdout,
Stderr,
MultiProgress(Arc<MultiProgress>),
Progress(Arc<ProgressBar>),
}
#[allow(unused)]
pub enum PromptDefault {
Yes,
No,
None,
}
impl LogHandler {
pub fn log_error(&self, msg: String) {
if self.is_loggable(Verbosity::Error) {
let msg = self.preformat_msg(msg);
let msg = format!("{} {}", ERR_SYMBOL.red().bold(), msg.bold().red());
self.log(msg);
}
}
pub fn log_warning(&self, msg: String) {
if self.is_loggable(Verbosity::Warning) {
let msg = self.preformat_msg(msg);
let msg = format!("{} {}", WARN_SYMBOL.yellow(), msg.yellow().bold());
self.log(msg);
}
}
pub fn log_info(&self, msg: String) {
if self.is_loggable(Verbosity::Info) {
let msg = self.preformat_msg(msg);
let msg = format!("{} {}", OK_SYMBOL.purple(), msg.bold());
self.log(msg);
}
}
pub fn log_debug(&self, msg: String) {
if self.is_loggable(Verbosity::Debug) {
let msg = self.preformat_msg(msg);
let msg = format!("{} {}", DEBUG_SYMBOL.blue(), msg);
self.log(msg);
}
}
pub fn log_trace(&self, msg: String) {
if self.is_loggable(Verbosity::Trace) {
let msg = self.preformat_msg(msg);
let msg = format!("{} {}", TRACE_SYMBOL.cyan(), msg.dimmed());
self.log(msg);
}
}
/// Prompts the user with a question and a default selection
pub fn prompt(&self, question: String, p_default: PromptDefault) -> bool {
let question = self.preformat_msg(question);
let question = format!("{} {}", PROMPT_SYMBOL.purple(), question.bold());
let mut confirm = Confirm::new();
confirm.with_prompt(question);
match p_default {
PromptDefault::Yes => {
confirm.default(true);
}
PromptDefault::No => {
confirm.default(false);
}
PromptDefault::None => {}
}
confirm.interact().unwrap()
}
pub fn set_verbosity(&self, level: Verbosity) {
(*self.level.write()) = level;
}
pub fn reset_output_type(&self) {
self.set_output_type(OutputType::Stdout);
}
/// Creates a new progress spinner and registers it on the log handler
pub fn new_progress_spinner(&self) -> Arc<ProgressBar> {
let progress_bar = ProgressBar::new_spinner().with_message("Scanning for pacnew files");
progress_bar.enable_steady_tick(Duration::from_millis(250));
let pb = Arc::new(progress_bar);
self.set_progress_bar(pb.clone());
pb
}
/// Registeres a progress bar on the log handler
pub fn set_progress_bar(&self, pb: Arc<ProgressBar>) {
self.set_output_type(OutputType::Progress(pb))
}
/// Sets the output type of the log handler to either stdout/stderr or a progress bar
pub fn set_output_type(&self, output: OutputType) {
(*self.output_type.write()) = output;
}
pub fn set_uwu_enabled(&self, enabled: bool) {
self.uwu_enabled
.store(enabled, std::sync::atomic::Ordering::Relaxed);
}
pub(crate) fn is_loggable(&self, level: Verbosity) -> bool {
(*self.level.read()) >= level
}
fn preformat_msg(&self, msg: String) -> String {
let msg = self.apply_uwu(msg);
let opts = textwrap::Options::new(crossterm::terminal::size().unwrap().0 as usize - 2)
.subsequent_indent(" ");
textwrap::wrap(&msg, opts).join("\n")
}
fn apply_uwu(&self, msg: String) -> String {
if self.uwu_enabled.load(std::sync::atomic::Ordering::Relaxed) {
uwu!(msg)
} else {
msg
}
}
fn log(&self, msg: String) {
let output_type = self.output_type.read();
match &*output_type {
OutputType::Stdout => println!("{}", msg),
OutputType::Stderr => eprintln!("{}", msg),
OutputType::MultiProgress(m) => {
let _ = m.println(msg);
}
OutputType::Progress(p) => p.println(msg),
};
}
}

@ -0,0 +1,69 @@
use std::sync::Arc;
use lazy_static::lazy_static;
use tracing::Level;
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
use tracing_subscriber::Registry;
mod fmt_layer;
use fmt_layer::AmeFormatLayer;
use crate::internal::uwu_enabled;
use self::handler::LogHandler;
pub mod handler;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Verbosity {
#[allow(dead_code)]
Error = 0,
#[allow(dead_code)]
Warning = 1,
Info = 2,
Debug = 3,
Trace = 4,
}
impl From<usize> for Verbosity {
fn from(num_verbosity: usize) -> Self {
match num_verbosity {
0 => Self::Info,
1 => Self::Debug,
2 => Self::Trace,
_ => Self::Info,
}
}
}
impl Verbosity {
fn from_level(l: &Level) -> Self {
match *l {
Level::ERROR => Self::Error,
Level::WARN => Self::Warning,
Level::INFO => Self::Info,
Level::DEBUG => Self::Debug,
Level::TRACE => Self::Trace,
}
}
}
/// Initializes the tracing logger
/// Can be used for debug purposes _or_ verbose output
pub fn init_logger(verbosity: Verbosity) {
let logger = get_logger();
logger.set_verbosity(verbosity);
logger.set_uwu_enabled(uwu_enabled());
let ame_layer = AmeFormatLayer::new(logger);
let subscriber = Registry::default().with(ame_layer);
tracing::subscriber::set_global_default(subscriber).unwrap();
}
/// Returns the global logger instance
pub fn get_logger() -> Arc<LogHandler> {
lazy_static! {
static ref LOGGER: Arc<LogHandler> = Arc::new(LogHandler::default());
}
Arc::clone(&LOGGER)
}

@ -10,34 +10,32 @@ use crate::internal::exit_code::AppExitCode;
use crate::internal::{init, sort, start_sudoloop, structs::Options}; use crate::internal::{init, sort, start_sudoloop, structs::Options};
use clap_complete::{Generator, Shell}; use clap_complete::{Generator, Shell};
use std::str::FromStr; use std::str::FromStr;
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::EnvFilter;
mod args; mod args;
mod builder; mod builder;
mod internal; mod internal;
mod logging;
mod operations; mod operations;
use logging::init_logger;
#[tokio::main(flavor = "current_thread")] #[tokio::main]
async fn main() { async fn main() {
color_eyre::install().unwrap(); color_eyre::install().unwrap();
if unsafe { libc::geteuid() } == 0 { 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"); 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");
} }
init_logger();
let args: Args = Args::parse(); let args: Args = Args::parse();
init_logger(args.verbose.into());
let verbosity = args.verbose;
let noconfirm = args.no_confirm; let noconfirm = args.no_confirm;
let options = Options { let options = Options {
verbosity,
noconfirm, noconfirm,
asdeps: false, asdeps: false,
}; };
init(options); init();
if args.sudoloop { if args.sudoloop {
start_sudoloop().await; start_sudoloop().await;
@ -49,11 +47,11 @@ async fn main() {
Operation::Search(search_args) => cmd_search(search_args, options).await, Operation::Search(search_args) => cmd_search(search_args, options).await,
Operation::Query(query_args) => cmd_query(query_args).await, Operation::Query(query_args) => cmd_query(query_args).await,
Operation::Upgrade(upgrade_args) => { Operation::Upgrade(upgrade_args) => {
info!("Performing system upgrade"); tracing::info!("Performing system upgrade");
operations::upgrade(upgrade_args, options).await; operations::upgrade(upgrade_args, options).await;
} }
Operation::Clean => { Operation::Clean => {
info!("Removing orphaned packages"); tracing::info!("Removing orphaned packages");
operations::clean(options).await; operations::clean(options).await;
} }
Operation::Info(info_args) => cmd_info(info_args).await, Operation::Info(info_args) => cmd_info(info_args).await,
@ -64,21 +62,6 @@ async fn main() {
detect().await; detect().await;
} }
/// Initializes the tracing logger
/// Can be used for debug purposes _or_ verbose output
fn init_logger() {
const DEFAULT_ENV_FILTER: &str = "warn";
let filter_string = std::env::var("AME_LOG").unwrap_or_else(|_| DEFAULT_ENV_FILTER.to_string());
let env_filter =
EnvFilter::from_str(&*filter_string).expect("failed to parse env filter string");
tracing_subscriber::fmt::SubscriberBuilder::default()
.with_env_filter(env_filter)
.with_writer(std::io::stdout)
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
.compact()
.init();
}
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
async fn cmd_install(args: InstallArgs, options: Options) { async fn cmd_install(args: InstallArgs, options: Options) {
let packages = args.packages; let packages = args.packages;
@ -113,14 +96,14 @@ async fn cmd_install(args: InstallArgs, options: Options) {
.split_whitespace() .split_whitespace()
.collect::<Vec<&str>>() .collect::<Vec<&str>>()
.join(", "); .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" ); tracing::info!("You have .pacnew files in /etc ({pacnew_files}) that you haven't removed or acted upon, it is recommended you do that now" );
} }
} }
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
async fn cmd_remove(args: RemoveArgs, options: Options) { async fn cmd_remove(args: RemoveArgs, options: Options) {
let packages = args.packages; let packages = args.packages;
info!("Uninstalling packages: {}", &packages.join(", ")); tracing::info!("Uninstalling packages: {}", &packages.join(", "));
operations::uninstall(packages, options).await; operations::uninstall(packages, options).await;
} }
@ -129,16 +112,16 @@ async fn cmd_search(args: SearchArgs, options: Options) {
let query_string = args.search; let query_string = args.search;
if args.aur { if args.aur {
info!("Searching AUR for {}", &query_string); tracing::info!("Searching AUR for {}", &query_string);
operations::aur_search(&query_string, args.by, options).await; operations::aur_search(&query_string, args.by, options).await;
} }
if args.repo { if args.repo {
info!("Searching repos for {}", &query_string); tracing::info!("Searching repos for {}", &query_string);
operations::search(&query_string, options).await; operations::search(&query_string, options).await;
} }
if !args.aur && !args.repo { if !args.aur && !args.repo {
info!("Searching AUR and repos for {}", &query_string); tracing::info!("Searching AUR and repos for {}", &query_string);
operations::search(&query_string, options).await; operations::search(&query_string, options).await;
operations::aur_search(&query_string, args.by, options).await; operations::aur_search(&query_string, args.by, options).await;
} }

@ -9,7 +9,7 @@ use crate::internal::commands::ShellCommand;
use crate::internal::error::SilentUnwrap; use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::internal::rpc::rpcinfo; use crate::internal::rpc::rpcinfo;
use crate::{crash, info, internal::fs_utils::rmdir_recursive, log, prompt, Options}; use crate::{crash, internal::fs_utils::rmdir_recursive, prompt, Options};
/// Installs a given list of packages from the aur /// Installs a given list of packages from the aur
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
@ -17,14 +17,11 @@ use crate::{crash, info, internal::fs_utils::rmdir_recursive, log, prompt, Optio
pub async fn aur_install(packages: Vec<String>, options: Options) { pub async fn aur_install(packages: Vec<String>, options: Options) {
let url = crate::internal::rpc::URL; let url = crate::internal::rpc::URL;
let cachedir = format!("{}/.cache/ame/", env::var("HOME").unwrap()); let cachedir = format!("{}/.cache/ame/", env::var("HOME").unwrap());
let verbosity = options.verbosity;
let noconfirm = options.noconfirm; let noconfirm = options.noconfirm;
if verbosity >= 1 { tracing::debug!("Installing from AUR: {:?}", &packages);
log!("Installing from AUR: {:?}", &packages);
}
info!("Installing packages {} from the AUR", packages.join(", ")); tracing::info!("Installing packages {} from the AUR", packages.join(", "));
for package_name in packages { for package_name in packages {
let rpcres = rpcinfo(&package_name) let rpcres = rpcinfo(&package_name)
@ -38,11 +35,9 @@ pub async fn aur_install(packages: Vec<String>, options: Options) {
let package = rpcres.unwrap(); let package = rpcres.unwrap();
let pkg_name = package.metadata.name; let pkg_name = package.metadata.name;
if verbosity >= 1 { tracing::debug!("Cloning {} into cachedir", pkg_name);
log!("Cloning {} into cachedir", pkg_name);
}
info!("Cloning package source"); tracing::info!("Cloning package source");
set_current_dir(Path::new(&cachedir)).unwrap(); set_current_dir(Path::new(&cachedir)).unwrap();
ShellCommand::git() ShellCommand::git()
@ -52,36 +47,31 @@ pub async fn aur_install(packages: Vec<String>, options: Options) {
.await .await
.silent_unwrap(AppExitCode::GitError); .silent_unwrap(AppExitCode::GitError);
if verbosity >= 1 { tracing::debug!(
log!( "Cloned {} into cachedir, moving on to resolving dependencies",
"Cloned {} into cachedir, moving on to resolving dependencies", pkg_name
pkg_name );
); tracing::debug!(
log!( "Raw dependencies for package {} are:\n{:?}",
"Raw dependencies for package {} are:\n{:?}", pkg_name,
pkg_name, package.depends,
package.depends, );
); tracing::debug!(
log!( "Raw makedepends for package {} are:\n{:?}",
"Raw makedepends for package {} are:\n{:?}", pkg_name,
pkg_name, package.make_depends.join(", "),
package.make_depends.join(", "), );
);
}
// dep sorting // dep sorting
log!("Sorting dependencies"); tracing::debug!("Sorting dependencies");
let sorted = crate::internal::sort(&package.depends, options).await; let sorted = crate::internal::sort(&package.depends, options).await;
log!("Sorting make dependencies"); tracing::debug!("Sorting make dependencies");
let md_sorted = crate::internal::sort(&package.make_depends, options).await; let md_sorted = crate::internal::sort(&package.make_depends, options).await;
if verbosity >= 1 { tracing::debug!("Sorted dependencies for {} are:\n{:?}", pkg_name, &sorted);
log!("Sorted dependencies for {} are:\n{:?}", pkg_name, &sorted); tracing::debug!("Sorted makedepends for {} are:\n{:?}", pkg_name, &md_sorted);
log!("Sorted makedepends for {} are:\n{:?}", pkg_name, &md_sorted);
}
let newopts = Options { let newopts = Options {
verbosity,
noconfirm, noconfirm,
asdeps: true, asdeps: true,
}; };
@ -96,7 +86,7 @@ pub async fn aur_install(packages: Vec<String>, options: Options) {
} }
if !noconfirm { if !noconfirm {
let p1 = prompt!(default false, let p1 = prompt!(default no,
"Would you like to review {}'s PKGBUILD (and any .install files if present)?", "Would you like to review {}'s PKGBUILD (and any .install files if present)?",
pkg_name, pkg_name,
); );
@ -126,7 +116,7 @@ pub async fn aur_install(packages: Vec<String>, options: Options) {
.silent_unwrap(AppExitCode::Other); .silent_unwrap(AppExitCode::Other);
} }
let p2 = prompt!(default true, "Would you still like to install {}?", pkg_name); let p2 = prompt!(default yes, "Would you still like to install {}?", pkg_name);
if !p2 { if !p2 {
fs::remove_dir_all(format!("{}/{}", cachedir, pkg_name)) fs::remove_dir_all(format!("{}/{}", cachedir, pkg_name))
.await .await
@ -137,7 +127,7 @@ pub async fn aur_install(packages: Vec<String>, options: Options) {
} }
// dep installing // dep installing
info!("Moving on to install dependencies"); tracing::info!("Moving on to install dependencies");
if !sorted.repo.is_empty() { if !sorted.repo.is_empty() {
crate::operations::install(sorted.repo, newopts).await; crate::operations::install(sorted.repo, newopts).await;
@ -157,7 +147,7 @@ pub async fn aur_install(packages: Vec<String>, options: Options) {
} }
// package building and installing // package building and installing
info!("Building time!"); tracing::info!("Building time!");
set_current_dir(format!("{}/{}", cachedir, pkg_name)).unwrap(); set_current_dir(format!("{}/{}", cachedir, pkg_name)).unwrap();
let status = ShellCommand::makepkg() let status = ShellCommand::makepkg()
.args(makepkg_args) .args(makepkg_args)

@ -1,18 +1,15 @@
use tokio::process::Command; use tokio::process::Command;
use crate::crash; use crate::crash;
use crate::info;
use crate::internal::commands::ShellCommand; use crate::internal::commands::ShellCommand;
use crate::internal::error::SilentUnwrap; use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::log;
use crate::prompt; use crate::prompt;
use crate::Options; use crate::Options;
/// Removes orphaned packages and cache /// Removes orphaned packages and cache
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
pub async fn clean(options: Options) { pub async fn clean(options: Options) {
let verbosity = options.verbosity;
let noconfirm = options.noconfirm; let noconfirm = options.noconfirm;
// Check for orphaned packages // Check for orphaned packages
@ -24,17 +21,17 @@ pub async fn clean(options: Options) {
if orphaned_packages.stdout.as_str().is_empty() { if orphaned_packages.stdout.as_str().is_empty() {
// If no orphaned packages found, do nothing // If no orphaned packages found, do nothing
info!("No orphaned packages found"); tracing::info!("No orphaned packages found");
} else { } else {
// Prompt users whether to remove orphaned packages // Prompt users whether to remove orphaned packages
info!( tracing::info!(
"Removing orphans would uninstall the following packages: \n{}", "Removing orphans would uninstall the following packages: \n{}",
&orphaned_packages.stdout &orphaned_packages.stdout
); );
let cont = prompt!(default false, "Continue?"); let cont = prompt!(default no, "Continue?");
if !cont { if !cont {
// If user doesn't want to continue, break // If user doesn't want to continue, break
info!("Exiting"); tracing::info!("Exiting");
std::process::exit(AppExitCode::PacmanError as i32); std::process::exit(AppExitCode::PacmanError as i32);
} }
@ -52,9 +49,7 @@ pub async fn clean(options: Options) {
} }
} }
if verbosity >= 1 { tracing::debug!("Removing orphans: {:?}", orphaned_packages_vec);
log!("Removing orphans: {:?}", orphaned_packages_vec);
}
// Remove orphaned packages // Remove orphaned packages
let pacman_result = ShellCommand::pacman() let pacman_result = ShellCommand::pacman()
@ -66,7 +61,7 @@ pub async fn clean(options: Options) {
if pacman_result.success() { if pacman_result.success() {
// If pacman succeeded, notify user // If pacman succeeded, notify user
info!("Successfully removed orphans"); tracing::info!("Successfully removed orphans");
} else { } else {
// If pacman failed, crash // If pacman failed, crash
crash!(AppExitCode::PacmanError, "Failed to remove orphans",); crash!(AppExitCode::PacmanError, "Failed to remove orphans",);
@ -74,7 +69,7 @@ pub async fn clean(options: Options) {
} }
// Prompt the user whether to clear the Amethyst cache // Prompt the user whether to clear the Amethyst cache
let clear_ame_cache = prompt!(default false, "Clear Amethyst's internal PKGBUILD cache?"); let clear_ame_cache = prompt!(default no, "Clear Amethyst's internal PKGBUILD cache?");
if clear_ame_cache { if clear_ame_cache {
// Remove ~/.cache/ame // Remove ~/.cache/ame
Command::new("rm") Command::new("rm")
@ -91,7 +86,7 @@ pub async fn clean(options: Options) {
let clear_pacman_cache = if noconfirm { let clear_pacman_cache = if noconfirm {
true true
} else { } else {
prompt!(default false, "Also clear pacman's package cache?") prompt!(default no, "Also clear pacman's package cache?")
}; };
if clear_pacman_cache { if clear_pacman_cache {
@ -107,9 +102,7 @@ pub async fn clean(options: Options) {
paccache_args.push("--noconfirm"); paccache_args.push("--noconfirm");
} }
if verbosity >= 1 { tracing::debug!("Clearing using `paccache -r`");
log!("Clearing using `paccache -r`");
}
// Clear pacman's cache (keeping latest 3 versions of installed packages) // Clear pacman's cache (keeping latest 3 versions of installed packages)
Command::new("sudo") Command::new("sudo")
@ -127,9 +120,7 @@ pub async fn clean(options: Options) {
.await .await
.unwrap(); .unwrap();
if verbosity >= 1 { tracing::debug!("Clearing using `pacman -Sc`");
log!("Clearing using `pacman -Sc`");
}
// Clear pacman's cache (keeping only installed packages) // Clear pacman's cache (keeping only installed packages)
let pacman_result = ShellCommand::pacman() let pacman_result = ShellCommand::pacman()
@ -141,7 +132,7 @@ pub async fn clean(options: Options) {
if pacman_result.success() { if pacman_result.success() {
// If pacman succeeded, notify user // If pacman succeeded, notify user
info!("Successfully cleared package cache"); tracing::info!("Successfully cleared package cache");
} else { } else {
// If pacman failed, crash // If pacman failed, crash
crash!(AppExitCode::PacmanError, "Failed to clear package cache",); crash!(AppExitCode::PacmanError, "Failed to clear package cache",);

@ -1,16 +1,13 @@
use crate::builder::pacman::PacmanInstallBuilder; use crate::builder::pacman::PacmanInstallBuilder;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::{crash, info, log, Options}; use crate::{crash, Options};
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
pub async fn install(packages: Vec<String>, options: Options) { pub async fn install(packages: Vec<String>, options: Options) {
info!("Installing packages {} from repos", &packages.join(", ")); tracing::info!("Installing packages {} from repos", &packages.join(", "));
let verbosity = options.verbosity;
if !packages.is_empty() { if !packages.is_empty() {
if verbosity >= 1 { tracing::debug!("Installing from repos: {:?}", &packages);
log!("Installing from repos: {:?}", &packages);
}
let result = PacmanInstallBuilder::from_options(options) let result = PacmanInstallBuilder::from_options(options)
.packages(packages.clone()) .packages(packages.clone())
@ -25,8 +22,6 @@ pub async fn install(packages: Vec<String>, options: Options) {
); );
} }
if verbosity >= 1 { tracing::debug!("Installing packages: {:?} was successful", &packages);
log!("Installing packages: {:?} was successful", &packages);
}
} }
} }

@ -4,12 +4,11 @@ use crate::internal::commands::ShellCommand;
use crate::internal::error::SilentUnwrap; use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::internal::rpc::rpcsearch; use crate::internal::rpc::rpcsearch;
use crate::{log, Options}; use crate::Options;
use aur_rpc::SearchField; use aur_rpc::SearchField;
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
pub async fn aur_search(query: &str, by_field: Option<SearchBy>, options: Options) { pub async fn aur_search(query: &str, by_field: Option<SearchBy>, options: Options) {
let verbosity = options.verbosity;
let packages = rpcsearch(query.to_string(), by_field.map(SearchBy::into)) let packages = rpcsearch(query.to_string(), by_field.map(SearchBy::into))
.await .await
.silent_unwrap(AppExitCode::RpcError); .silent_unwrap(AppExitCode::RpcError);
@ -22,14 +21,11 @@ pub async fn aur_search(query: &str, by_field: Option<SearchBy>, options: Option
) )
} }
if verbosity >= 1 { tracing::debug!("Found {total_results} resuls for \"{query}\" in AUR",);
log!("Found {total_results} resuls for \"{query}\" in AUR",);
}
} }
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
pub async fn repo_search(query: &str, options: Options) { pub async fn repo_search(query: &str, options: Options) {
let verbosity = options.verbosity;
let output = ShellCommand::pacman() let output = ShellCommand::pacman()
.arg("-Ss") .arg("-Ss")
.arg(query) .arg(query)
@ -38,13 +34,11 @@ pub async fn repo_search(query: &str, options: Options) {
.silent_unwrap(AppExitCode::PacmanError) .silent_unwrap(AppExitCode::PacmanError)
.stdout; .stdout;
if verbosity >= 1 { tracing::debug!(
log!( "Found {} results for \"{}\" in repos",
"Found {} results for \"{}\" in repos", &output.split('\n').count() / 2,
&output.split('\n').count() / 2, &query
&query );
);
}
println!("{}", output) println!("{}", output)
} }

@ -5,7 +5,7 @@ use tokio::fs;
use crate::internal::commands::ShellCommand; use crate::internal::commands::ShellCommand;
use crate::internal::error::SilentUnwrap; use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::{log, Options}; use crate::Options;
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
pub async fn uninstall(packages: Vec<String>, options: Options) { pub async fn uninstall(packages: Vec<String>, options: Options) {
@ -15,10 +15,7 @@ pub async fn uninstall(packages: Vec<String>, options: Options) {
if options.noconfirm { if options.noconfirm {
pacman_args.push("--noconfirm"); pacman_args.push("--noconfirm");
} }
let verbosity = options.verbosity; tracing::debug!("Uninstalling: {:?}", &packages);
if verbosity >= 1 {
log!("Uninstalling: {:?}", &packages);
}
ShellCommand::pacman() ShellCommand::pacman()
.elevated() .elevated()
@ -27,9 +24,7 @@ pub async fn uninstall(packages: Vec<String>, options: Options) {
.await .await
.silent_unwrap(AppExitCode::PacmanError); .silent_unwrap(AppExitCode::PacmanError);
if verbosity >= 1 { tracing::debug!("Uninstalling packages: {:?} exited with code 0", &packages);
log!("Uninstalling packages: {:?} exited with code 0", &packages);
}
for package in packages { for package in packages {
if Path::new(&format!( if Path::new(&format!(
@ -39,9 +34,7 @@ pub async fn uninstall(packages: Vec<String>, options: Options) {
)) ))
.exists() .exists()
{ {
if verbosity >= 1 { tracing::debug!("Old cache directory found, deleting");
log!("Old cache directory found, deleting");
}
fs::remove_dir_all(Path::new(&format!( fs::remove_dir_all(Path::new(&format!(
"{}/.cache/ame/{}", "{}/.cache/ame/{}",
env::var("HOME").unwrap(), env::var("HOME").unwrap(),

@ -5,7 +5,7 @@ use crate::internal::error::SilentUnwrap;
use crate::internal::exit_code::AppExitCode; use crate::internal::exit_code::AppExitCode;
use crate::internal::rpc::rpcinfo; use crate::internal::rpc::rpcinfo;
use crate::operations::aur_install::aur_install; use crate::operations::aur_install::aur_install;
use crate::{info, log, prompt, warn, Options}; use crate::{prompt, Options};
/// Upgrades all installed packages /// Upgrades all installed packages
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
@ -16,11 +16,14 @@ pub async fn upgrade(args: UpgradeArgs, options: Options) {
if args.aur { if args.aur {
upgrade_aur(options).await; upgrade_aur(options).await;
} }
if !args.aur && !args.repo {
upgrade_repo(options).await;
upgrade_aur(options).await;
}
} }
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
async fn upgrade_repo(options: Options) { async fn upgrade_repo(options: Options) {
let verbosity = options.verbosity;
let noconfirm = options.noconfirm; let noconfirm = options.noconfirm;
let mut pacman_args = vec!["-Syu"]; let mut pacman_args = vec!["-Syu"];
@ -28,9 +31,7 @@ async fn upgrade_repo(options: Options) {
pacman_args.push("--noconfirm"); pacman_args.push("--noconfirm");
} }
if verbosity >= 1 { tracing::debug!("Upgrading repo packages");
log!("Upgrading repo packages");
}
let pacman_result = ShellCommand::pacman() let pacman_result = ShellCommand::pacman()
.elevated() .elevated()
@ -40,13 +41,13 @@ async fn upgrade_repo(options: Options) {
.silent_unwrap(AppExitCode::PacmanError); .silent_unwrap(AppExitCode::PacmanError);
if pacman_result.success() { if pacman_result.success() {
info!("Successfully upgraded repo packages"); tracing::info!("Successfully upgraded repo packages");
} else { } else {
let continue_upgrading = prompt!(default false, let continue_upgrading = prompt!(default no,
"Failed to upgrade repo packages, continue to upgrading AUR packages?", "Failed to upgrade repo packages, continue to upgrading AUR packages?",
); );
if !continue_upgrading { if !continue_upgrading {
info!("Exiting"); tracing::info!("Exiting");
std::process::exit(AppExitCode::PacmanError as i32); std::process::exit(AppExitCode::PacmanError as i32);
} }
} }
@ -54,11 +55,7 @@ async fn upgrade_repo(options: Options) {
#[tracing::instrument(level = "trace")] #[tracing::instrument(level = "trace")]
async fn upgrade_aur(options: Options) { async fn upgrade_aur(options: Options) {
let verbosity = options.verbosity; tracing::debug!("Upgrading AUR packages");
if verbosity >= 1 {
log!("Upgrading AUR packages");
}
let non_native_pkgs = PacmanQueryBuilder::foreign() let non_native_pkgs = PacmanQueryBuilder::foreign()
.color(PacmanColor::Never) .color(PacmanColor::Never)
@ -84,13 +81,13 @@ async fn upgrade_aur(options: Options) {
aur_upgrades.push(pkg.name); aur_upgrades.push(pkg.name);
} }
} else { } else {
warn!("Could not find the remote package for {}", pkg.name); tracing::warn!("Could not find the remote package for {}", pkg.name);
} }
} }
if !aur_upgrades.is_empty() { if !aur_upgrades.is_empty() {
aur_install(aur_upgrades, options).await; aur_install(aur_upgrades, options).await;
} else { } else {
info!("No upgrades available for installed AUR packages"); tracing::info!("No upgrades available for installed AUR packages");
} }
} }

Loading…
Cancel
Save