Revised error handling and some cleanup

- `fatal()` function for handling the termination of the program when a
  fatal human-readable error digestable error occurs. This function
  terminates the program and will never return a value.
- Much like the aforementioned function, the `error()` function now
  prints the error and terminates the program, instead of printing the
  error and returning the error code as an i32 integer.
- ErrorType enum implemented as an encapsulate to delineate error type.
- Display trait implemented for ErrorType enum for use cases whereby
  the program being terminated is inconvenient for the given code path.
- `generic()` function added to GenericError trait for handling errors
  of which do not require a message to be prepended.
- Global configuration is now statically cached with OnceLock instead of
  lazy_static, and is loaded on-demand instead of during the invocation
  of the `init()` function from the init module upon program startup.
- Use of lazy_static was also eliminated in pacwrap-core's sync module.
This commit is contained in:
Xavier Moffett 2024-09-19 21:16:50 -04:00
parent ed5b112538
commit d1622eb0b4
Signed by: Sapphirus
GPG key ID: A6C061B2CEA1A7AC
22 changed files with 161 additions and 110 deletions

View file

@ -99,7 +99,7 @@ fn conduct_transaction(config: &Global, handle: &mut TransactionHandle, agent: T
err!(SyncError::InitializationFailure(error.to_string()))?
}
handle.ignore(&mut None);
handle.ignore(&mut None)?;
if let TransactionType::Upgrade(upgrade, downgrade, _) = action {
if upgrade {

View file

@ -37,6 +37,6 @@ fn main() {
};
if let Err(error) = result {
error.handle();
error.error();
}
}

View file

@ -39,7 +39,7 @@ pub use self::{
container::{Container, ContainerHandle, ContainerType},
dbus::Dbus,
filesystem::{BindError, Filesystem},
global::{Global, CONFIG},
global::{global, Global},
permission::{PermError, Permission},
vars::ContainerVariables,
};
@ -149,7 +149,7 @@ fn handle<'a>(vars: ContainerVariables) -> Result<ContainerHandle<'a>> {
}
}
fn config() -> Result<Global> {
fn load_config() -> Result<Global> {
match serde_yaml::from_reader(File::open(*CONFIG_FILE).prepend_io(|| CONFIG_FILE.to_string())?) {
Ok(file) => Ok(file),
Err(error) => err!(ConfigError::Load(CONFIG_FILE.to_string(), error.to_string()))?,

View file

@ -17,21 +17,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::process::exit;
use std::sync::OnceLock;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use crate::{
config::{config, save},
config::{load_config, save},
constants::CONFIG_FILE,
sync::event::summary::SummaryKind,
Result,
};
lazy_static! {
pub static ref CONFIG: Global = Global::load();
}
static CONFIG: OnceLock<Global> = OnceLock::new();
#[derive(Serialize, Deserialize, Clone)]
pub enum Verbosity {
@ -188,13 +185,6 @@ impl Default for Global {
}
impl Global {
fn load() -> Self {
match config() {
Ok(config) => config,
Err(error) => exit(error.error()),
}
}
pub fn new() -> Self {
Self {
config: Configuration::new(),
@ -215,6 +205,20 @@ impl Global {
}
}
pub fn global() -> Result<&'static Global> {
Ok(match CONFIG.get() {
Some(f) => f,
None => {
let cfg = match load_config() {
Ok(config) => Ok(config),
Err(error) => error.fatal(),
}?;
CONFIG.get_or_init(|| cfg)
}
})
}
fn ignore_pkg() -> Vec<String> {
vec!["".into()]
}

View file

@ -20,7 +20,6 @@
use std::{fs::File, io::Write, path::Path};
use crate::{
config::global::CONFIG,
constants::{CACHE_DIR, CONFIG_DIR, DATA_DIR},
err,
Error,
@ -97,9 +96,5 @@ pub fn init() -> Result<()> {
data_layout().instantiate()?;
cache_layout().instantiate()?;
initialize_file(&format!("{}/repositories.conf", *CONFIG_DIR), REPO_CONF_DEFAULT)?;
initialize_file(&format!("{}/pacwrap.yml", *CONFIG_DIR), PACWRAP_CONF_DEFAULT)?;
let _ = *CONFIG;
Ok(())
initialize_file(&format!("{}/pacwrap.yml", *CONFIG_DIR), PACWRAP_CONF_DEFAULT)
}

View file

@ -32,6 +32,7 @@ use crate::{
exec::args::ExecutionArgs,
Error,
ErrorGeneric,
ErrorType,
};
static GPU_DEV: OnceLock<Vec<String>> = OnceLock::new();
@ -42,8 +43,8 @@ struct Graphics;
#[typetag::serde(name = "gpu")]
impl Permission for Graphics {
fn check(&self) -> Result<Option<Condition>, PermError> {
let gpu_dev = populate_dev().map_err(|f| {
f.error();
let gpu_dev = populate_dev().map_err(|error| {
eprintln!("{}", ErrorType::Error(&error));
Fail("No graphics devices are available.".into())
})?;
let nvidia = !gpu_dev.iter().filter(|a| a.contains("nvidia")).collect::<Vec<_>>().is_empty();

View file

@ -17,11 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{
env::var,
process::{exit, id},
time::Duration,
};
use std::{env::var, process::id, time::Duration};
use lazy_static::lazy_static;
use nix::unistd::{getegid, geteuid};
@ -109,7 +105,7 @@ lazy_static! {
}
fn env(env: &'static str) -> &'static str {
var(env).map_or_else(|_| exit(error!(ErrorKind::EnvVarUnset(env)).error()), |var| var.leak())
var(env).map_or_else(|_| error!(ErrorKind::EnvVarUnset(env)).fatal(), |var| var.leak())
}
fn env_opt(env: &str) -> &'static str {

View file

@ -62,12 +62,20 @@ pub trait Downcast {
}
pub trait ErrorGeneric<R, E> {
fn prepend<F>(self, f: F) -> StdResult<R, Error>
fn prepend<F>(self, f: F) -> Result<R>
where
F: FnOnce() -> String;
fn prepend_io<F>(self, f: F) -> StdResult<R, Error>
fn prepend_io<F>(self, f: F) -> Result<R>
where
F: FnOnce() -> String;
fn generic(self) -> Result<R>;
}
#[derive(Debug)]
pub enum ErrorType<'a> {
Error(&'a Error),
Warn(&'a Error),
Fatal(&'a Error),
}
#[derive(Debug)]
@ -86,18 +94,18 @@ impl Error {
Self { kind: err }
}
pub fn handle(&self) {
eprintln!("{}error:{} {}", *BOLD_RED, *RESET, self.kind);
exit(self.kind.code());
pub fn fatal(&self) -> ! {
eprintln!("{}", ErrorType::Fatal(self));
exit(self.kind.code())
}
pub fn error(&self) -> i32 {
eprintln!("{}error:{} {}", *BOLD_RED, *RESET, self.kind);
self.kind.code()
pub fn error(&self) -> ! {
eprintln!("{}", ErrorType::Error(self));
exit(self.kind.code())
}
pub fn warn(&self) {
eprintln!("{}warning:{} {}", *BOLD_YELLOW, *RESET, self.kind);
eprintln!("{}", ErrorType::Warn(self))
}
#[allow(clippy::borrowed_box)]
@ -113,13 +121,21 @@ impl Error {
}
}
impl_error!(GenericError);
impl Display for ErrorType<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::Fatal(e) => write!(f, "{}fatal:{} {}", *BOLD_RED, *RESET, e.kind),
Self::Error(e) => write!(f, "{}error:{} {}", *BOLD_RED, *RESET, e.kind),
Self::Warn(e) => write!(f, "{}warning:{} {}", *BOLD_YELLOW, *RESET, e.kind),
}
}
}
impl<R, E> ErrorGeneric<R, E> for StdResult<R, E>
where
E: Display,
{
fn prepend<F>(self, f: F) -> StdResult<R, Error>
fn prepend<F>(self, f: F) -> Result<R>
where
F: FnOnce() -> String, {
match self {
@ -131,7 +147,7 @@ where
}
}
fn prepend_io<F>(self, f: F) -> StdResult<R, Error>
fn prepend_io<F>(self, f: F) -> Result<R>
where
F: FnOnce() -> String, {
match self {
@ -142,6 +158,16 @@ where
}),
}
}
fn generic(self) -> Result<R> {
match self {
Ok(f) => Ok(f),
Err(err) => err!(GenericError {
prepend: "An error has occurred".into(),
error: err.to_string(),
}),
}
}
}
impl Display for GenericError {
@ -150,6 +176,8 @@ impl Display for GenericError {
}
}
impl_error!(GenericError);
impl<T> Downcast for T
where
T: ErrorTrait + 'static,

View file

@ -31,15 +31,15 @@ use serde::Serialize;
use serde_yaml::Value;
use crate::{
config::CONFIG,
config::global,
constants::BWRAP_EXECUTABLE,
err,
error::*,
exec::{ExecutionError, ExecutionType},
sync::{
alpm_config,
transaction::{TransactionMetadata, TransactionParameters},
SyncError,
DEFAULT_ALPM_CONF,
},
utils::TermControl,
ErrorKind,
@ -155,8 +155,8 @@ pub fn agent_params(
metadata: &TransactionMetadata,
) -> Result<i32> {
serialize(params, writer)?;
serialize(&*CONFIG, writer)?;
serialize(&*DEFAULT_ALPM_CONF, writer)?;
serialize(global()?, writer)?;
serialize(alpm_config()?, writer)?;
serialize(metadata, writer)?;
Ok(reader.as_raw_fd())
}

View file

@ -21,20 +21,18 @@ use std::{
fs::{create_dir, create_dir_all},
os::unix::fs::symlink,
path::Path,
process::exit,
sync::OnceLock,
time::{SystemTime, UNIX_EPOCH},
};
use alpm::{Alpm, LogLevel, SigLevel, Usage};
use lazy_static::lazy_static;
use pacmanconf::{self, Config, Repository};
use serde::{Deserialize, Serialize};
use crate::{
config::{global::ProgressKind, ContainerHandle, ContainerType::*, ContainerVariables, Global, CONFIG},
config::{global, global::ProgressKind, ContainerHandle, ContainerType::*, ContainerVariables, Global},
constants::{ARROW_RED, BAR_GREEN, BOLD, CACHE_DIR, CONFIG_DIR, DATA_DIR, RESET, UNIX_TIMESTAMP, VERBOSE},
err,
error,
exec::pacwrap_key,
impl_error,
sync::{
@ -57,11 +55,8 @@ pub mod utils;
mod resolver;
mod resolver_local;
lazy_static! {
pub static ref DEFAULT_ALPM_CONF: AlpmConfigData = AlpmConfigData::new();
static ref PACMAN_CONF: pacmanconf::Config = load_repositories();
static ref DEFAULT_SIGLEVEL: SigLevel = default_signature();
}
static PACMAN_CONFIG: OnceLock<pacmanconf::Config> = OnceLock::new();
static ALPM_CONFIG_DATA: OnceLock<AlpmConfigData> = OnceLock::new();
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SyncError {
@ -145,7 +140,7 @@ impl From<&Repository> for AlpmRepository {
Self {
name: repo.name.clone(),
mirrors: repo.servers.clone(),
sig_lvl: signature(&repo.sig_level, *DEFAULT_SIGLEVEL).bits(),
sig_lvl: signature(&repo.sig_level, default_signature()).bits(),
}
}
}
@ -170,23 +165,33 @@ pub struct AlpmConfigData {
}
impl AlpmConfigData {
fn new() -> Self {
Self {
repos: PACMAN_CONF.repos.iter().map(|a| a.into()).collect(),
}
fn new() -> Result<Self> {
Ok(Self {
repos: pacman_conf()?.repos.iter().map(|a| a.into()).collect(),
})
}
}
fn alpm_log_callback(level: LogLevel, msg: &str, counter: &mut usize) {
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let time = now.as_secs() as usize - *counter;
let nano = now.subsec_nanos().to_string();
let log_level = level.bits() / 4;
let verbosity = if *VERBOSE { 3 } else { 2 };
pub fn alpm_config() -> Result<&'static AlpmConfigData> {
Ok(match ALPM_CONFIG_DATA.get() {
Some(data) => data,
None => {
let data = AlpmConfigData::new()?;
if log_level < verbosity {
eprint!("[{}.{:.6}] [ALPM] {}", time, nano, msg);
}
ALPM_CONFIG_DATA.get_or_init(|| data)
}
})
}
fn pacman_conf() -> Result<&'static Config> {
Ok(match PACMAN_CONFIG.get() {
Some(c) => c,
None => {
let cfg = load_pacman_conf()?;
PACMAN_CONFIG.get_or_init(|| cfg)
}
})
}
pub fn instantiate_alpm_agent(config: &Global, remotes: &AlpmConfigData, transflags: &TransactionFlags) -> Alpm {
@ -215,14 +220,20 @@ pub fn instantiate_alpm_agent(config: &Global, remotes: &AlpmConfigData, transfl
handle
}
pub fn instantiate_alpm(inshandle: &ContainerHandle, transflags: &TransactionFlags) -> Alpm {
alpm_handle(inshandle.vars(), &DEFAULT_ALPM_CONF, transflags, format!("{}/var/lib/pacman/", inshandle.vars().root()))
pub fn instantiate_alpm(inshandle: &ContainerHandle, transflags: &TransactionFlags) -> Result<Alpm> {
alpm_handle(inshandle.vars(), alpm_config()?, transflags, format!("{}/var/lib/pacman/", inshandle.vars().root()))
}
fn alpm_handle(insvars: &ContainerVariables, remotes: &AlpmConfigData, transflags: &TransactionFlags, db_path: String) -> Alpm {
fn alpm_handle(
insvars: &ContainerVariables,
remotes: &AlpmConfigData,
transflags: &TransactionFlags,
db_path: String,
) -> Result<Alpm> {
let config = global()?;
let mut handle = Alpm::new(insvars.root(), &db_path).expect("Unable to acquire ALPM handle");
let debug = transflags.intersects(TransactionFlags::DEBUG);
let disable_sandbox = CONFIG.alpm().disable_sandbox() || transflags.intersects(TransactionFlags::NO_ALPM_SANDBOX);
let disable_sandbox = config.alpm().disable_sandbox() || transflags.intersects(TransactionFlags::NO_ALPM_SANDBOX);
if debug {
handle.set_log_cb(*UNIX_TIMESTAMP as usize, alpm_log_callback);
@ -236,11 +247,23 @@ fn alpm_handle(insvars: &ContainerVariables, remotes: &AlpmConfigData, transflag
handle.set_logfile(format!("{}/pacwrap.log", *DATA_DIR)).expect("set logfile");
handle.set_gpgdir(format!("{}/pacman/gnupg", *DATA_DIR)).expect("set gpgdir");
handle.set_cachedirs([format!("{}/pkg", *CACHE_DIR)].iter()).expect("set cachedirs");
handle.set_parallel_downloads(CONFIG.alpm().parallel_downloads());
handle.set_disable_dl_timeout(CONFIG.alpm().download_timeout());
handle.set_check_space(CONFIG.alpm().check_space());
handle.set_parallel_downloads(config.alpm().parallel_downloads());
handle.set_disable_dl_timeout(config.alpm().download_timeout());
handle.set_check_space(global()?.alpm().check_space());
handle = register_remote(handle, remotes);
handle
Ok(handle)
}
fn alpm_log_callback(level: LogLevel, msg: &str, counter: &mut usize) {
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let time = now.as_secs() as usize - *counter;
let nano = now.subsec_nanos().to_string();
let log_level = level.bits() / 4;
let verbosity = if *VERBOSE { 3 } else { 2 };
if log_level < verbosity {
eprint!("[{}.{:.6}] [ALPM] {}", time, nano, msg);
}
}
pub fn instantiate_container<'a>(handle: &'a ContainerHandle<'a>) -> Result<()> {
@ -312,7 +335,7 @@ fn synchronize_database(ag: &mut TransactionAggregator, force: bool) -> Result<(
};
let flags = ag.flags();
let db_path = format!("{}/pacman/", *DATA_DIR);
let mut handle = alpm_handle(handle.vars(), &DEFAULT_ALPM_CONF, flags, db_path);
let mut handle = alpm_handle(handle.vars(), alpm_config()?, flags, db_path)?;
ag.lock()?.assert()?;
println!("{} {}Synchronizing package databases...{}", *BAR_GREEN, *BOLD, *RESET);
@ -326,7 +349,7 @@ fn synchronize_database(ag: &mut TransactionAggregator, force: bool) -> Result<(
ag.lock()?.assert()?;
for handle in ag.cache().filter_handle(vec![Base, Slice, Aggregate]).iter() {
for repo in PACMAN_CONF.repos.iter() {
for repo in pacman_conf()?.repos.iter() {
let src = &format!("{}/pacman/sync/{}.db", *DATA_DIR, repo.name);
let dest = &format!("{}/var/lib/pacman/sync/{}.db", handle.vars().root(), repo.name);
@ -363,13 +386,13 @@ fn signature(sigs: &Vec<String>, default: SigLevel) -> SigLevel {
}
fn default_signature() -> SigLevel {
signature(&CONFIG.alpm().sig_level(), SigLevel::PACKAGE | SigLevel::DATABASE_OPTIONAL)
signature(&global().expect("pacwrap.yml").alpm().sig_level(), SigLevel::PACKAGE | SigLevel::DATABASE_OPTIONAL)
}
fn load_repositories() -> Config {
fn load_pacman_conf() -> Result<Config> {
let path = format!("{}/repositories.conf", *CONFIG_DIR);
match Config::from_file(&path) {
Ok(match Config::from_file(&path) {
Ok(config) => config,
Err(error) => {
//The following code is ugly, precisely because, the pacman_conf library does not
@ -377,9 +400,8 @@ fn load_repositories() -> Config {
let error = error.to_string();
let error = error.split("error: ").collect::<Vec<_>>()[1].split("\n").collect::<Vec<&str>>()[0];
let error = error!(SyncError::RepoConfError(path, error.to_string()));
exit(error.error());
err!(SyncError::RepoConfError(path, error.to_string()))?
}
}
})
}

View file

@ -26,7 +26,7 @@ use serde::{Deserialize, Serialize};
use self::{SyncState::*, TransactionMode::*, TransactionType::*};
use crate::{
config::{ContainerHandle, Global, CONFIG},
config::{global, ContainerHandle, Global},
constants::{ARROW_CYAN, BAR_CYAN, BOLD, BOLD_GREEN, BOLD_YELLOW, RESET},
err,
log::{Level, Logger},
@ -326,11 +326,11 @@ impl<'a> TransactionHandle<'a> {
.extend(self.meta.foreign_pkgs.iter().map(|p| p.to_owned().into()).collect::<Vec<_>>());
}
pub fn ignore(&mut self, log: &mut Option<&mut Logger>) {
pub fn ignore(&mut self, log: &mut Option<&mut Logger>) -> Result<()> {
let alpm = self.alpm.as_mut().unwrap();
let config = match self.config {
Some(config) => config,
None => &*CONFIG,
None => global()?,
};
let local = match self.meta.mode {
Local => &self.meta.resident_pkgs,
@ -391,6 +391,8 @@ impl<'a> TransactionHandle<'a> {
*BOLD, *RESET, *BOLD_YELLOW, *RESET, *BOLD_GREEN, *RESET
));
}
Ok(())
}
pub fn prepare(&mut self, trans_type: &TransactionType, flags: &TransactionFlags) -> Result<()> {
@ -402,7 +404,7 @@ impl<'a> TransactionHandle<'a> {
let queue = self.meta.queue.iter().map(|i| i.as_ref()).collect::<Vec<_>>();
let config = match self.config {
Some(config) => config,
None => &*CONFIG,
None => global()?,
};
if let Local = self.meta.mode {

View file

@ -17,10 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{
collections::{HashMap, HashSet},
process::exit,
};
use std::collections::{HashMap, HashSet};
use alpm::Alpm;
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
@ -245,7 +242,7 @@ impl<'a> TransactionAggregator<'a> {
None => Vec::new(),
};
let alpm = sync::instantiate_alpm(inshandle, self.flags());
let alpm = sync::instantiate_alpm(inshandle, self.flags())?;
let mut meta = TransactionMetadata::new(queue);
let mut handle = TransactionHandle::new(&mut meta).alpm_handle(alpm);
let mut act: Box<dyn Transaction> = Prepare.from(self);
@ -292,7 +289,7 @@ impl<'a> TransactionAggregator<'a> {
return match err.downcast::<SyncError>().map_err(|err| error!(SyncError::from(err)))? {
SyncError::TransactionAgentFailure => {
self.logger().log(Level::Fatal, &format!("Transaction error: {:?}", err))?;
exit(err.kind().code())
err.fatal()
}
_ => {
self.logger().log(Level::Error, &format!("Transaction error: {:?}", err))?;

View file

@ -20,7 +20,10 @@
use std::{os::unix::process::ExitStatusExt, process::Child, result::Result as StdResult};
use crate::{
config::{ContainerHandle, CONFIG},
config::{
global::{global, Global},
ContainerHandle,
},
constants::{BOLD, RESET},
err,
exec::transaction_agent,
@ -84,7 +87,7 @@ impl Transaction for Commit {
erroneous_preparation(error)?
}
let result = confirm(&self.state, ag, handle);
let result = confirm(&self.state, ag, handle, global()?);
let result = match result {
Err(result) => return result,
Ok(result) => result,
@ -102,7 +105,7 @@ impl Transaction for Commit {
ag.keyring_update(inshandle)?;
}
handle.set_alpm(Some(sync::instantiate_alpm(inshandle, ag.flags())));
handle.set_alpm(Some(sync::instantiate_alpm(inshandle, ag.flags())?));
handle.apply_configuration(inshandle, ag.flags().intersects(TransactionFlags::CREATE))?;
ag.logger().log(Info, &format!("container {instance}'s {state} transaction complete"))?;
next_state(handle, ag.action(), &self.state, true)
@ -117,6 +120,7 @@ fn confirm(
state: &TransactionState,
ag: &TransactionAggregator,
handle: &mut TransactionHandle,
global: &'static Global,
) -> StdResult<(u64, u64), Result<TransactionState>> {
let database = ag.flags().intersects(TransactionFlags::DATABASE_ONLY | TransactionFlags::FORCE_DATABASE);
let foreign = !handle.get_mode().bool();
@ -126,7 +130,7 @@ fn confirm(
};
let confirm = foreign || database && !create;
let sum = Summary::new()
.kind(CONFIG.config().summary(), confirm)
.kind(global.config().summary(), confirm)
.mode(handle.get_mode())
.generate(handle.alpm());

View file

@ -70,7 +70,7 @@ impl Transaction for Prepare {
if !deps.is_empty() {
for dep in deps.iter().rev() {
match ag.cache().get_instance_option(dep) {
Some(dep_handle) => handle.enumerate_package_lists(&sync::instantiate_alpm(dep_handle, ag.flags())),
Some(dep_handle) => handle.enumerate_package_lists(&sync::instantiate_alpm(dep_handle, ag.flags())?),
None => err!(SyncError::DependentContainerMissing(dep.to_string()))?,
}
}

View file

@ -80,7 +80,7 @@ impl Transaction for Stage {
ag.action().action_message(self.mode);
handle.set_mode(self.mode);
handle.ignore(&mut ag.flags().contains(TransactionFlags::DEBUG).then_some(ag.logger()));
handle.ignore(&mut ag.flags().contains(TransactionFlags::DEBUG).then_some(ag.logger()))?;
handle.meta.set_flags(ag.flags(), &self.flags);
match ag.action() {

View file

@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{process::exit, thread::Builder};
use std::thread::Builder;
use alpm::{
Alpm,
@ -197,7 +197,7 @@ pub fn signal_trap() {
println!();
if count == 3 {
exit(error!(SyncError::SignalInterrupt).error());
error!(SyncError::SignalInterrupt).error()
}
}
})

View file

@ -39,6 +39,7 @@ use pacwrap_core::{
Error,
ErrorGeneric,
ErrorKind,
ErrorType,
Result,
};
@ -52,7 +53,7 @@ pub fn compose(args: &mut Arguments) -> Result<()> {
let result = engage_aggregator(args, &lock);
if let Err(error) = lock.unlock() {
error.error();
eprintln!("{}", ErrorType::Error(&error));
}
result

View file

@ -47,6 +47,6 @@ fn main() {
};
if let Err(error) = result {
error.handle();
error.error();
}
}

View file

@ -55,7 +55,7 @@ pub fn query(arguments: &mut Arguments) -> Result<()> {
}
let handle = config::provide_handle(target)?;
let handle = instantiate_alpm(&handle, &flags);
let handle = instantiate_alpm(&handle, &flags)?;
for pkg in handle.localdb().pkgs() {
if explicit && pkg.reason() != PackageReason::Explicit {

View file

@ -49,7 +49,7 @@ pub fn remove(args: &mut Arguments) -> Result<()> {
let result = engage_aggregator(action, args, &mut logger, &lock);
if let Err(error) = lock.unlock() {
error.error();
eprintln!("{}", ErrorType::Error(&error));
}
result

View file

@ -51,7 +51,7 @@ pub fn synchronize(args: &mut Arguments) -> Result<()> {
let result = engage_aggregator(&mut cache, &mut logger, args, &lock, action, create);
if let Err(error) = lock.unlock() {
error.error();
eprintln!("{}", ErrorType::Error(&error));
}
result

View file

@ -36,6 +36,7 @@ use pacwrap_core::{
ErrorGeneric,
ErrorKind,
ErrorTrait,
ErrorType,
Result,
};
@ -93,7 +94,7 @@ pub fn remove_containers(args: &mut Arguments) -> Result<()> {
if let (true, _) | (_, true) = (no_confirm, prompt_targets(&instances, "Delete containers?", false)) {
if let Err(err) = delete_roots(&cache, &lock, &mut logger, &instances, force) {
err.error();
eprintln!("{}", ErrorType::Error(&err));
}
}