Genericised From<T>
trait impl for Error types
- Error type in the error module now implements a broadly generic From<T> impl for error conversion into the pacwrap-core library's Error type. - `ErrorGeneric::prepend` and `ErrorGeneric::prepend_io` both now accept borrowed or heap-allocated String return types without additional sugar. - A lone unary postfix operator has been applied to external function calls where deemed most appropriate, removing unnecessary function calls to `ErrorGeneric::prepend` and `ErrorGeneric::prepend_io`.
This commit is contained in:
parent
6e5bb8df5a
commit
f20f46b28e
17 changed files with 119 additions and 111 deletions
|
@ -67,7 +67,7 @@ pub fn transact() -> Result<()> {
|
|||
}
|
||||
};
|
||||
|
||||
file.read_exact_at(header.as_slice_mut(), 0).prepend_io(|| AGENT_PARAMS.into())?;
|
||||
file.read_exact_at(header.as_slice_mut(), 0).prepend_io(|| AGENT_PARAMS)?;
|
||||
decode_header(&mut header)?;
|
||||
|
||||
let params: TransactionParameters = deserialize(&mut file)?;
|
||||
|
|
|
@ -130,13 +130,13 @@ pub fn provide_new_handle<'a>(instance: &'a str, instype: ContainerType, deps: V
|
|||
}
|
||||
|
||||
fn save<T: Serialize>(obj: &T, path: &str) -> Result<()> {
|
||||
let mut f = File::create(path).prepend_io(|| path.into())?;
|
||||
let mut f = File::create(path).prepend_io(|| path)?;
|
||||
let config = match serde_yaml::to_string(&obj) {
|
||||
Ok(file) => file,
|
||||
Err(error) => err!(ConfigError::Save(path.into(), error.to_string()))?,
|
||||
};
|
||||
|
||||
write!(f, "{}", config).prepend_io(|| path.into())
|
||||
write!(f, "{}", config).prepend_io(|| path)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -158,7 +158,7 @@ fn handle<'a>(vars: ContainerVariables) -> Result<ContainerHandle<'a>> {
|
|||
}
|
||||
|
||||
fn load_config() -> Result<Global> {
|
||||
match serde_yaml::from_reader(File::open(*CONFIG_FILE).prepend_io(|| CONFIG_FILE.to_string())?) {
|
||||
match serde_yaml::from_reader(File::open(*CONFIG_FILE).prepend_io(|| *CONFIG_FILE)?) {
|
||||
Ok(file) => Ok(file),
|
||||
Err(error) => err!(ConfigError::Load(CONFIG_FILE.to_string(), error.to_string()))?,
|
||||
}
|
||||
|
|
|
@ -210,9 +210,9 @@ pub fn global() -> Result<&'static Global> {
|
|||
Some(f) => f,
|
||||
None => {
|
||||
let cfg = match load_config() {
|
||||
Ok(config) => Ok(config),
|
||||
Err(error) => error.fatal(),
|
||||
}?;
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => err.fatal(),
|
||||
};
|
||||
|
||||
CONFIG.get_or_init(|| cfg)
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ fn initialize_file(location: &str, contents: &str) -> Result<()> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
write!(File::create(location).prepend_io(|| location.into())?, "{contents}").prepend_io(|| location.into())?;
|
||||
write!(File::create(location).prepend_io(|| location)?, "{contents}").prepend_io(|| location)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -81,13 +81,13 @@ impl Permission for Graphics {
|
|||
|
||||
fn populate_dev() -> Result<Vec<String>, Error> {
|
||||
Ok(read_dir("/dev/")
|
||||
.prepend_io(|| "/dev".into())?
|
||||
.prepend_io(|| "/dev")?
|
||||
.filter_map(|f| {
|
||||
f.map_or_else(
|
||||
|_| None,
|
||||
|f| {
|
||||
let file = f.file_name();
|
||||
let dev = file.to_str().unwrap();
|
||||
let dev = file.to_str().expect("UTF-8 path");
|
||||
|
||||
(dev.starts_with("nvidia") || dev == "dri").then_some(format!("/dev/{}", dev))
|
||||
},
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
use std::{
|
||||
any::Any,
|
||||
error::Error as StdError,
|
||||
fmt::{Debug, Display, Formatter, Result as FmtResult},
|
||||
process::exit,
|
||||
result::Result as StdResult,
|
||||
|
@ -62,12 +63,14 @@ pub trait Downcast {
|
|||
}
|
||||
|
||||
pub trait ErrorGeneric<R, E> {
|
||||
fn prepend<F>(self, f: F) -> Result<R>
|
||||
fn prepend<Y, Z>(self, f: Y) -> Result<R>
|
||||
where
|
||||
F: FnOnce() -> String;
|
||||
fn prepend_io<F>(self, f: F) -> Result<R>
|
||||
Z: AsRef<str>,
|
||||
Y: FnOnce() -> Z;
|
||||
fn prepend_io<Y, Z>(self, f: Y) -> Result<R>
|
||||
where
|
||||
F: FnOnce() -> String;
|
||||
Z: AsRef<str>,
|
||||
Y: FnOnce() -> Z;
|
||||
fn generic(self) -> Result<R>;
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,7 @@ pub enum ErrorType<'a> {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct GenericError {
|
||||
prepend: String,
|
||||
prepend: Option<String>,
|
||||
error: String,
|
||||
}
|
||||
|
||||
|
@ -141,44 +144,49 @@ impl<R, E> ErrorGeneric<R, E> for StdResult<R, E>
|
|||
where
|
||||
E: Display,
|
||||
{
|
||||
fn prepend<F>(self, f: F) -> Result<R>
|
||||
fn prepend<Y, Z>(self, f: Y) -> Result<R>
|
||||
where
|
||||
F: FnOnce() -> String, {
|
||||
Z: AsRef<str>,
|
||||
Y: FnOnce() -> Z, {
|
||||
match self {
|
||||
Ok(f) => Ok(f),
|
||||
Err(err) => err!(GenericError {
|
||||
prepend: f(),
|
||||
prepend: Some(f().as_ref().into()),
|
||||
error: err.to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn prepend_io<F>(self, f: F) -> Result<R>
|
||||
fn prepend_io<Y, Z>(self, f: Y) -> Result<R>
|
||||
where
|
||||
F: FnOnce() -> String, {
|
||||
match self {
|
||||
Ok(f) => Ok(f),
|
||||
Err(err) => err!(GenericError {
|
||||
prepend: format!("'{}'", f()),
|
||||
error: err.to_string(),
|
||||
}),
|
||||
}
|
||||
Z: AsRef<str>,
|
||||
Y: FnOnce() -> Z, {
|
||||
self.prepend(|| format!("'{}'", f().as_ref()))
|
||||
}
|
||||
|
||||
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(),
|
||||
}),
|
||||
}
|
||||
self.prepend(|| "An error has occurred")
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Error
|
||||
where
|
||||
T: StdError + ToString,
|
||||
{
|
||||
fn from(err: T) -> Self {
|
||||
error!(GenericError {
|
||||
prepend: None,
|
||||
error: err.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for GenericError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "{}: {}", self.prepend, self.error)
|
||||
match &self.prepend {
|
||||
None => write!(f, "{}", self.error),
|
||||
Some(prepend) => write!(f, "{}: {}", prepend, self.error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ impl Logger {
|
|||
let path = Path::new(location);
|
||||
let file = OpenOptions::new().create(true).append(true).truncate(false).open(path);
|
||||
|
||||
self.file = Some(file.prepend_io(|| location.into())?);
|
||||
self.file = Some(file.prepend_io(|| location)?);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
|
@ -175,9 +175,7 @@ impl Logger {
|
|||
* time offset if a change were to occur whilst this application is running.
|
||||
*/
|
||||
if let Ok(local) = OffsetDateTime::now_local() {
|
||||
let local_time = local.format(UTC_OFFSET).expect("Format localtime");
|
||||
|
||||
self.offset = UtcOffset::parse(&local_time, UTC_OFFSET).expect("Offset localtime");
|
||||
self.offset = UtcOffset::parse(&local.format(UTC_OFFSET)?, UTC_OFFSET)?;
|
||||
}
|
||||
|
||||
if let Level::Debug = level {
|
||||
|
@ -190,10 +188,10 @@ impl Logger {
|
|||
|
||||
match self.file.as_mut() {
|
||||
Some(file) => {
|
||||
let time = OffsetDateTime::now_utc().to_offset(self.offset).format(DATE_FORMAT).expect("Format time");
|
||||
let time = OffsetDateTime::now_utc().to_offset(self.offset).format(DATE_FORMAT)?;
|
||||
let log = format!("[{}] [{}] [{}] {}\n", time, self.module, level, msg);
|
||||
|
||||
file.write(log.as_bytes()).generic()
|
||||
Ok(file.write(log.as_bytes())?)
|
||||
}
|
||||
None => err!(LoggerError::Uninitialized)?,
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ pub fn list<'a>(cache: &'a ContainerCache<'a>) -> Result<ProcessList> {
|
|||
|
||||
fn procfs() -> Result<Vec<(i32, u64)>> {
|
||||
Ok(read_dir("/proc/")
|
||||
.prepend_io(|| "/proc/".into())?
|
||||
.prepend_io(|| "/proc/")?
|
||||
.filter_map(StdResult::ok)
|
||||
.filter_map(|s| procfs_meta(s).unwrap_or(None))
|
||||
.filter_map(|(name, mtime)| {
|
||||
|
|
|
@ -285,14 +285,14 @@ pub fn instantiate_container<'a>(handle: &'a ContainerHandle<'a>) -> Result<()>
|
|||
let dep = handle.metadata().dependencies();
|
||||
let dep = dep.last().expect("Dependency element");
|
||||
|
||||
symlink(dep, root).prepend_io(|| root.into())?;
|
||||
symlink(dep, root).prepend_io(|| root)?;
|
||||
} else {
|
||||
create_dir(root).prepend_io(|| root.into())?;
|
||||
create_dir(root).prepend_io(|| root)?;
|
||||
}
|
||||
|
||||
if let Aggregate | Base = container_type {
|
||||
if !Path::new(home).exists() {
|
||||
create_dir(home).prepend_io(|| home.into())?;
|
||||
create_dir(home).prepend_io(|| home)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,7 +320,7 @@ pub fn instantiate_trust() -> Result<()> {
|
|||
err!(SyncError::UnableToLocateKeyrings)?
|
||||
}
|
||||
|
||||
create_dir_all(path).prepend_io(|| path.into())?;
|
||||
create_dir_all(path).prepend_io(|| path)?;
|
||||
pacwrap_key(vec!["--init"])?;
|
||||
pacwrap_key(vec!["--populate"])
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ fn synchronize_database(ag: &mut TransactionAggregator, force: bool) -> Result<(
|
|||
err!(SyncError::InitializationFailure(err.to_string()))?
|
||||
}
|
||||
|
||||
handle.release().generic()?;
|
||||
handle.release()?;
|
||||
ag.lock()?.assert()?;
|
||||
|
||||
for handle in ag.cache().filter_handle(vec![Base, Slice, Aggregate]).iter() {
|
||||
|
|
|
@ -21,7 +21,7 @@ use std::{
|
|||
collections::{HashMap, HashSet},
|
||||
fmt::{Display, Formatter, Result as FmtResult},
|
||||
fs::{self, create_dir_all, hard_link, metadata, remove_dir_all, remove_file, rename, File, Metadata},
|
||||
io::{copy, BufReader, Error as IOError, ErrorKind as IOErrorKind, Read, Result as IOResult, Write},
|
||||
io::{copy, BufReader, ErrorKind as IOErrorKind, Read, Result as IOResult, Write},
|
||||
os::unix::{fs::symlink, prelude::MetadataExt},
|
||||
path::Path,
|
||||
sync::{
|
||||
|
@ -81,6 +81,9 @@ pub enum FilesystemSyncError {
|
|||
UnsupportedVersion(String, u32),
|
||||
DeserializationFailure(String, String),
|
||||
SerializationFailure(String, String),
|
||||
DataLengthMaximum(u64, u64),
|
||||
DataLengthZero,
|
||||
InvalidHashLength,
|
||||
}
|
||||
|
||||
impl_error!(FilesystemSyncError);
|
||||
|
@ -95,6 +98,9 @@ impl Display for FilesystemSyncError {
|
|||
write!(fmter, "Deserialization failure occurred with '{}{file}{}.dat': {err}", *BOLD, *RESET),
|
||||
Self::ChecksumMismatch(file) => write!(fmter, "'{file}': Checksum mismatch"),
|
||||
Self::MagicMismatch(file, magic) => write!(fmter, "'{file}': Magic number mismatch ({MAGIC_NUMBER} != {magic})"),
|
||||
Self::DataLengthZero => write!(fmter, "Data length provided is zero"),
|
||||
Self::InvalidHashLength => write!(fmter, "Hash length provided is invalid."),
|
||||
Self::DataLengthMaximum(cur, max) => write!(fmter, "Data length exceeded maximum {cur} >= {max}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,11 +288,11 @@ impl<'a> FilesystemSync<'a> {
|
|||
if let IOErrorKind::NotFound = err.kind() {
|
||||
return Ok(None);
|
||||
} else {
|
||||
return Err(err).prepend_io(|| path.into());
|
||||
return Err(err).prepend_io(|| path);
|
||||
},
|
||||
};
|
||||
|
||||
file.read_exact(header.as_slice_mut()).prepend_io(|| path.into())?;
|
||||
file.read_exact(header.as_slice_mut()).prepend_io(|| path)?;
|
||||
|
||||
let magic = header.read_le_32();
|
||||
let version = header.read_le_32();
|
||||
|
@ -302,7 +308,7 @@ impl<'a> FilesystemSync<'a> {
|
|||
self.state_map_prev.insert(instance.clone(), Some(state.clone()));
|
||||
Ok(Some(state))
|
||||
} else {
|
||||
let (state_buffer, checksum_valid) = decode_state(file).prepend_io(|| path.into())?;
|
||||
let (state_buffer, checksum_valid) = decode_state(file).prepend_io(|| path)?;
|
||||
|
||||
if !checksum_valid {
|
||||
err!(FilesystemSyncError::ChecksumMismatch(path.into()))?
|
||||
|
@ -543,12 +549,12 @@ fn serialize(path: &str, ds: FileSystemState) -> Result<()> {
|
|||
err!(FilesystemSyncError::SerializationFailure(path.into(), err.as_ref().to_string()))?
|
||||
}
|
||||
|
||||
copy(&mut state_data.as_slice(), &mut hasher).prepend_io(|| path.into())?;
|
||||
encode_state(path, state_data, hasher.finalize().to_vec()).prepend_io(|| path.into())?;
|
||||
copy(&mut state_data.as_slice(), &mut hasher).prepend_io(|| path)?;
|
||||
encode_state(path, state_data, hasher.finalize().to_vec()).prepend_io(|| path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn decode_state<R: Read>(mut stream: R) -> IOResult<(Vec<u8>, bool)> {
|
||||
fn decode_state<R: Read>(mut stream: R) -> Result<(Vec<u8>, bool)> {
|
||||
let mut header_buffer = ByteBuffer::with_capacity(10).read();
|
||||
|
||||
stream.read_exact(header_buffer.as_slice_mut())?;
|
||||
|
@ -557,11 +563,11 @@ fn decode_state<R: Read>(mut stream: R) -> IOResult<(Vec<u8>, bool)> {
|
|||
let state_length = header_buffer.read_le_64();
|
||||
|
||||
if state_length == 0 {
|
||||
Err(IOError::new(IOErrorKind::InvalidInput, "Data length provided is zero".to_string()))?;
|
||||
err!(FilesystemSyncError::DataLengthZero)?;
|
||||
} else if hash_length != 32 {
|
||||
Err(IOError::new(IOErrorKind::InvalidInput, "Hash length provided is invalid.".to_string()))?;
|
||||
err!(FilesystemSyncError::InvalidHashLength)?;
|
||||
} else if state_length >= BYTE_LIMIT {
|
||||
Err(IOError::new(IOErrorKind::InvalidInput, format!("Data length exceeded maximum {state_length} >= {BYTE_LIMIT}")))?;
|
||||
err!(FilesystemSyncError::DataLengthMaximum(state_length, BYTE_LIMIT))?;
|
||||
}
|
||||
|
||||
let mut hash_buffer = vec![0; hash_length as usize];
|
||||
|
@ -594,9 +600,9 @@ fn encode_state(path: &str, state_data: Vec<u8>, hash: Vec<u8>) -> IOResult<u64>
|
|||
fn check(instance: &str) -> Result<bool> {
|
||||
let path = &format!("{}/state/{}.dat", *DATA_DIR, instance);
|
||||
let mut header_buffer = ByteBuffer::with_capacity(8).read();
|
||||
let mut file = File::open(path).prepend_io(|| path.into())?;
|
||||
let mut file = File::open(path).prepend_io(|| path)?;
|
||||
|
||||
file.read_exact(header_buffer.as_slice_mut()).prepend_io(|| path.into())?;
|
||||
file.read_exact(header_buffer.as_slice_mut())?;
|
||||
|
||||
let magic = header_buffer.read_le_32();
|
||||
let version = header_buffer.read_le_32();
|
||||
|
|
|
@ -141,16 +141,16 @@ pub fn extract(inshandle: &ContainerHandle, old_schema: &Option<SchemaState>) ->
|
|||
}
|
||||
|
||||
for entry in access_archive(ARCHIVE_PATH)?.entries().unwrap() {
|
||||
let mut entry = entry.prepend_io(|| ARCHIVE_PATH.into())?;
|
||||
let path = entry.path().prepend_io(|| ARCHIVE_PATH.into())?.to_string_lossy().to_string();
|
||||
let mut entry = entry.prepend_io(|| ARCHIVE_PATH)?;
|
||||
let path = entry.path().prepend_io(|| ARCHIVE_PATH)?.to_string_lossy().to_string();
|
||||
let dest_path = format!("{}/{}", inshandle.vars().root(), path);
|
||||
|
||||
if let Err(err) = entry.unpack(&dest_path).prepend_io(|| ARCHIVE_PATH.into()) {
|
||||
if let Err(err) = entry.unpack(&dest_path).prepend_io(|| ARCHIVE_PATH) {
|
||||
err.warn();
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = fs::copy(env!("PACWRAP_DIST_META"), &meta_path).prepend_io(|| ARCHIVE_PATH.into()) {
|
||||
if let Err(err) = fs::copy(env!("PACWRAP_DIST_META"), &meta_path).prepend_io(|| ARCHIVE_PATH) {
|
||||
err.warn();
|
||||
}
|
||||
|
||||
|
@ -171,14 +171,14 @@ pub fn version(inshandle: &ContainerHandle) -> Result<SchemaStatus> {
|
|||
}
|
||||
};
|
||||
|
||||
file.read_exact(header.as_slice_mut()).prepend_io(|| schema.into())?;
|
||||
file.read_exact(header.as_slice_mut()).prepend_io(|| schema)?;
|
||||
|
||||
let magic = header.read_le_32();
|
||||
let major: (u32, u32) = (*VERSION_MAJOR, header.read_le_32());
|
||||
let minor: (u32, u32) = (*VERSION_MINOR, header.read_le_32());
|
||||
let patch: (u32, u32) = (*VERSION_PATCH, header.read_le_32());
|
||||
|
||||
file.rewind().prepend_io(|| schema.into())?;
|
||||
file.rewind().prepend_io(|| schema)?;
|
||||
|
||||
if magic != MAGIC_NUMBER {
|
||||
print_warning(&format!("'{}': Magic number mismatch ({MAGIC_NUMBER} != {magic})", schema));
|
||||
|
@ -221,20 +221,20 @@ fn get_schema_state() -> Result<&'static SchemaState> {
|
|||
|
||||
fn deserialize() -> Result<SchemaState> {
|
||||
let schema = env!("PACWRAP_DIST_META");
|
||||
let file = File::open(schema).prepend_io(|| schema.into())?;
|
||||
let file = File::open(schema).prepend_io(|| schema)?;
|
||||
|
||||
bincode::deserialize_from::<&File, SchemaState>(&file).prepend(|| format!("Schema deserialization failure '{schema}'"))
|
||||
}
|
||||
|
||||
fn access_archive<'a>(path: &str) -> Result<Archive<Decoder<'a, BufReader<File>>>> {
|
||||
Ok(Archive::new(Decoder::new(File::open(path).prepend_io(|| path.into())?).prepend_io(|| path.into())?))
|
||||
Ok(Archive::new(Decoder::new(File::open(path).prepend_io(|| path)?).prepend_io(|| path)?))
|
||||
}
|
||||
|
||||
fn remove_file(path: &str) -> Result<()> {
|
||||
if Path::new(&format!("{}.pacnew", &path)).exists() {
|
||||
fs::remove_file(path).prepend(|| format!("Failed to remove '{path}'"))?;
|
||||
fs::remove_file(path).prepend(|| path)?;
|
||||
} else {
|
||||
fs::copy(format!("{}.pacnew", &path), path).prepend(|| format!("Failed to copy '{path}'"))?;
|
||||
fs::copy(format!("{}.pacnew", &path), path).prepend_io(|| format!("{}.pacnew", &path))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -242,7 +242,7 @@ fn remove_file(path: &str) -> Result<()> {
|
|||
|
||||
fn remove_symlink(path: &str) -> Result<()> {
|
||||
if fs::read_link(path).is_ok() {
|
||||
fs::remove_file(path).prepend(|| format!("Failed to remove symlink '{path}'"))?;
|
||||
fs::remove_file(path).prepend_io(|| path)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -253,9 +253,9 @@ fn remove_directory(path: &str) -> Result<()> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
fs::remove_dir(path).prepend(|| format!("Failed to remove directory '{path}'"))
|
||||
fs::remove_dir(path).prepend_io(|| path)
|
||||
}
|
||||
|
||||
fn is_directory_occupied(path: &str) -> Result<bool> {
|
||||
Ok(fs::read_dir(path).prepend_io(|| path.into())?.count() > 0)
|
||||
Ok(fs::read_dir(path).prepend_io(|| path)?.count() > 0)
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ use crate::{
|
|||
},
|
||||
utils::prompt::prompt,
|
||||
Error,
|
||||
ErrorGeneric,
|
||||
Result,
|
||||
};
|
||||
|
||||
|
@ -79,7 +78,7 @@ impl Transaction for Commit {
|
|||
let state = self.state.as_str();
|
||||
|
||||
if let SyncState::NotRequired = handle.trans_ready(ag.action(), ag.flags())? {
|
||||
handle.alpm_mut().trans_release().generic()?;
|
||||
handle.alpm_mut().trans_release()?;
|
||||
|
||||
return Ok(match ready_state(ag.action(), &self.state) {
|
||||
Some(state) => state,
|
||||
|
@ -138,7 +137,7 @@ fn confirm(
|
|||
println!("{}", sum);
|
||||
|
||||
if ag.flags().contains(TransactionFlags::PREVIEW) {
|
||||
handle.alpm_mut().trans_release().generic()?;
|
||||
handle.alpm_mut().trans_release()?;
|
||||
return Ok(State::Next(next_state(ag.action(), state, false)));
|
||||
}
|
||||
|
||||
|
@ -147,13 +146,13 @@ fn confirm(
|
|||
let query = format!("Proceed with {action}?");
|
||||
|
||||
if !prompt("::", format!("{}{query}{}", *BOLD, *RESET), true)? {
|
||||
handle.alpm_mut().trans_release().generic()?;
|
||||
handle.alpm_mut().trans_release()?;
|
||||
return Ok(State::Next(next_state(ag.action(), state, false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle.alpm_mut().trans_release().generic()?;
|
||||
handle.alpm_mut().trans_release()?;
|
||||
Ok(State::Commit(sum.download()))
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ use crate::{
|
|||
err,
|
||||
impl_error,
|
||||
Error,
|
||||
ErrorGeneric,
|
||||
ErrorTrait,
|
||||
Result,
|
||||
};
|
||||
|
@ -55,34 +54,35 @@ impl Display for PromptError {
|
|||
|
||||
impl_error!(PromptError);
|
||||
|
||||
pub fn prompt(prefix: &str, prompt: impl Into<String>, yn_prompt: bool) -> Result<bool> {
|
||||
let value = create_prompt(prompt.into(), prefix, yn_prompt)?;
|
||||
pub fn prompt(prefix: impl AsRef<str>, prompt: impl AsRef<str>, yn_prompt: bool) -> Result<bool> {
|
||||
let value = create_prompt(prompt.as_ref(), prefix.as_ref(), yn_prompt)?;
|
||||
|
||||
Ok(value.to_lowercase() == "y" || (yn_prompt && value.is_empty()))
|
||||
}
|
||||
|
||||
fn create_prompt(message: String, prefix: &str, yn_prompt: bool) -> Result<String> {
|
||||
fn create_prompt<T: AsRef<str>>(message: T, prefix: T, yn_prompt: bool) -> Result<String> {
|
||||
let prefix = prefix.as_ref();
|
||||
let prompt = match yn_prompt {
|
||||
true => ("[Y/n]", style(prefix.into()).blue().bold()),
|
||||
false => ("[y/N]", style(prefix.into()).red().bold()),
|
||||
};
|
||||
|
||||
let theme = ColorfulTheme {
|
||||
success_prefix: style(prefix.into()).green().bold(),
|
||||
prompt_prefix: prompt.1,
|
||||
success_prefix: style(prefix.into()).green().bold(),
|
||||
error_prefix: style(prefix.into()).red().bold(),
|
||||
prompt_suffix: style(prompt.0.to_string()).bold(),
|
||||
success_suffix: style(prompt.0.to_string()).bold(),
|
||||
prompt_suffix: style(prompt.0.into()).bold(),
|
||||
success_suffix: style(prompt.0.into()).bold(),
|
||||
prompt_style: Style::new(),
|
||||
values_style: Style::new(),
|
||||
..ColorfulTheme::default()
|
||||
};
|
||||
let input: String = match Input::with_theme(&theme).with_prompt(message).allow_empty(true).interact_text() {
|
||||
let input: String = match Input::with_theme(&theme).with_prompt(message.as_ref()).allow_empty(true).interact_text() {
|
||||
Ok(prompt) => prompt,
|
||||
Err(error) => match error.kind() {
|
||||
Interrupted => err!(PromptError::PromptInterrupted)?,
|
||||
NotConnected => err!(PromptError::PromptNotTerminal)?,
|
||||
_ => Err(error).generic()?,
|
||||
_ => Err(error)?,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ fn engage_aggregator(args: &mut Arguments, lock: &Lock) -> Result<()> {
|
|||
delete.push(target);
|
||||
}
|
||||
|
||||
Path::new(target).try_exists().prepend_io(|| target.into())?;
|
||||
Path::new(target).try_exists().prepend_io(|| target)?;
|
||||
|
||||
current_target.map(|_| config)
|
||||
} else {
|
||||
|
|
|
@ -50,7 +50,7 @@ fn list_desktop_entries(args: &mut Arguments) -> Result<()> {
|
|||
Ok(instance) => (false, format!("{}/usr/share/applications", provide_handle(instance)?.vars().root())),
|
||||
Err(_) => (true, format!("{}/.local/share/applications", *HOME)),
|
||||
};
|
||||
let dir = read_dir(app_dir).prepend_io(|| app_dir.into())?;
|
||||
let dir = read_dir(app_dir).prepend_io(|| app_dir)?;
|
||||
|
||||
for entry in dir {
|
||||
if let Some(file) = entry.prepend(|| format!("Failure acquiring entry in '{app_dir}'"))?.file_name().to_str() {
|
||||
|
@ -69,7 +69,7 @@ fn list_desktop_entries(args: &mut Arguments) -> Result<()> {
|
|||
fn create_desktop_entry(args: &mut Arguments) -> Result<()> {
|
||||
let target = args.target()?;
|
||||
let app_dir = &format!("{}/usr/share/applications", provide_handle(target)?.vars().root());
|
||||
let dir = read_dir(app_dir).prepend_io(|| app_dir.into())?;
|
||||
let dir = read_dir(app_dir).prepend_io(|| app_dir)?;
|
||||
let name = &match args.next().unwrap_or_default() {
|
||||
Operand::Value(val) | Operand::ShortPos(_, val) | Operand::LongPos(_, val) => val,
|
||||
_ => return args.invalid_operand(),
|
||||
|
@ -97,25 +97,25 @@ fn create_desktop_entry(args: &mut Arguments) -> Result<()> {
|
|||
let mut contents = String::new();
|
||||
|
||||
File::open(desktop_file)
|
||||
.prepend_io(|| desktop_file.into())?
|
||||
.prepend_io(|| desktop_file)?
|
||||
.read_to_string(&mut contents)
|
||||
.prepend_io(|| desktop_file.into())?;
|
||||
.prepend_io(|| desktop_file)?;
|
||||
contents = Regex::new("Exec=*")
|
||||
.unwrap()
|
||||
.replace_all(&contents, format!("Exec=pacwrap run {} ", target))
|
||||
.to_string();
|
||||
|
||||
let desktop_file = &format!("{}/.local/share/applications/pacwrap.{}", *HOME, file_name);
|
||||
let mut output = File::create(desktop_file).prepend_io(|| desktop_file.into())?;
|
||||
let mut output = File::create(desktop_file).prepend_io(|| desktop_file)?;
|
||||
|
||||
write!(output, "{}", contents).prepend_io(|| desktop_file.into())?;
|
||||
write!(output, "{}", contents).prepend_io(|| desktop_file)?;
|
||||
eprintln!("{} Created '{}'.", *ARROW_GREEN, file_name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_desktop_entry(args: &mut Arguments) -> Result<()> {
|
||||
let app_dir = &format!("{}/.local/share/applications", *HOME);
|
||||
let dir = read_dir(app_dir).prepend_io(|| app_dir.into())?;
|
||||
let dir = read_dir(app_dir).prepend_io(|| app_dir)?;
|
||||
let name = &match args.next().unwrap_or_default() {
|
||||
Operand::Value(val) | Operand::ShortPos(_, val) | Operand::LongPos(_, val) => val,
|
||||
_ => return args.invalid_operand(),
|
||||
|
@ -141,7 +141,7 @@ fn remove_desktop_entry(args: &mut Arguments) -> Result<()> {
|
|||
};
|
||||
let desktop_file = &format!("{}/.local/share/applications/{}", *HOME, file_name);
|
||||
|
||||
remove_file(desktop_file).prepend_io(|| desktop_file.into())?;
|
||||
remove_file(desktop_file).prepend_io(|| desktop_file)?;
|
||||
eprintln!("{} Removed '{file_name}'.", *ARROW_GREEN);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ pub fn edit(args: &mut Arguments, edit: bool) -> Result<()> {
|
|||
}
|
||||
|
||||
fn edit_file(file: &str, temporary_file: &str, lock: Option<&Lock>, edit: bool) -> Result<()> {
|
||||
copy(file, temporary_file).prepend_io(|| file.into())?;
|
||||
copy(file, temporary_file).prepend_io(|| file)?;
|
||||
handle_process(*EDITOR, Command::new(*EDITOR).arg(temporary_file).spawn())?;
|
||||
|
||||
if edit && hash_file(file)? != hash_file(temporary_file)? {
|
||||
|
@ -136,19 +136,19 @@ fn edit_file(file: &str, temporary_file: &str, lock: Option<&Lock>, edit: bool)
|
|||
lock.assert()?;
|
||||
}
|
||||
|
||||
copy(temporary_file, file).prepend_io(|| temporary_file.into())?;
|
||||
copy(temporary_file, file).prepend_io(|| temporary_file)?;
|
||||
eprintln!("{} Changes written to file.", *ARROW_GREEN);
|
||||
} else if edit {
|
||||
eprintln!("{} No changes made.", *ARROW_CYAN);
|
||||
}
|
||||
|
||||
remove_file(temporary_file).prepend_io(|| temporary_file.into())
|
||||
remove_file(temporary_file).prepend_io(|| temporary_file)
|
||||
}
|
||||
|
||||
fn hash_file(file_path: &str) -> Result<Vec<u8>> {
|
||||
let mut file = File::open(file_path).prepend_io(|| file_path.into())?;
|
||||
let mut file = File::open(file_path).prepend_io(|| file_path)?;
|
||||
let mut hasher = Sha256::new();
|
||||
|
||||
copy_io(&mut file, &mut hasher).prepend_io(|| file_path.into())?;
|
||||
copy_io(&mut file, &mut hasher).prepend_io(|| file_path)?;
|
||||
Ok(hasher.finalize().to_vec())
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ pub fn list_containers(args: &mut Arguments) -> Result<()> {
|
|||
let instance = container.vars().instance();
|
||||
let container_path = &format!("{}/{}", *CONTAINER_DIR, instance);
|
||||
let (len, organic, total) = if measure_disk && container.metadata().container_type() != &ContainerType::Symbolic {
|
||||
directory_size(container_path)?
|
||||
directory_size(container_path).prepend_io(|| container_path)?
|
||||
} else {
|
||||
(0, 0, 0)
|
||||
};
|
||||
|
@ -223,17 +223,14 @@ fn directory_size(dir: &str) -> Result<(i64, i64, i64)> {
|
|||
let mut total = 0;
|
||||
let mut unique = 0;
|
||||
|
||||
for entry in read_dir(dir).prepend_io(|| dir.into())? {
|
||||
let entry = entry.prepend(|| format!("Failure acquiring entry in '{dir}'"))?;
|
||||
let name = entry.file_name().to_str().unwrap().to_string();
|
||||
let meta = entry.metadata().prepend(|| format!("Failure to acquire metadata in '{dir}/{name}'"))?;
|
||||
for entry in read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let meta = entry.metadata()?;
|
||||
|
||||
if entry
|
||||
.file_type()
|
||||
.prepend(|| format!("Failure to acquire filetype '{dir}/{name}'"))?
|
||||
.is_dir()
|
||||
{
|
||||
let (l, u, t) = directory_size(&format!("{dir}/{name}"))?;
|
||||
if entry.file_type()?.is_dir() {
|
||||
let path = entry.file_name();
|
||||
let path = path.to_str().expect("UTF-8 path");
|
||||
let (l, u, t) = directory_size(&format!("{dir}/{path}"))?;
|
||||
|
||||
len += l;
|
||||
unique += u;
|
||||
|
|
Loading…
Reference in a new issue