updated error types

This commit is contained in:
Emma Tebibyte 2023-03-27 00:01:32 -04:00
parent 623d65be0d
commit 3eedea2f9c
Signed by: emma
GPG Key ID: 6D661C738815E7DD
5 changed files with 138 additions and 102 deletions

33
Cargo.lock generated
View File

@ -62,15 +62,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "c-main"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "797bbff8bd2bcddb7f0ee638b55398686adac15174689a86da5ffc0f51219f75"
dependencies = [
"libc",
]
[[package]]
name = "cc"
version = "1.0.79"
@ -300,7 +291,6 @@ name = "hopper"
version = "0.1.0"
dependencies = [
"arg",
"c-main",
"console",
"curl",
"dialoguer",
@ -380,6 +370,15 @@ version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]]
name = "libc-print"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06cea5d58bd9ba4717bbf5c6c5bb11bb6e9e76685b7fff34039b80f50ce86c11"
dependencies = [
"libc",
]
[[package]]
name = "libloading"
version = "0.7.4"
@ -551,9 +550,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "proc-macro2"
version = "1.0.53"
version = "1.0.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
dependencies = [
"unicode-ident",
]
@ -1010,16 +1009,16 @@ dependencies = [
[[package]]
name = "yacexits"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe740dd05c1bbc919431e842e6c1bea30195e0518ae99cae35b7f0730ddc18"
version = "0.2.0"
source = "git+https://git.tebibyte.media/yac/yacexits.git?branch=c-entry#d2af983f4ad18dec2af0604d7f34b7863daa5c25"
dependencies = [
"bindgen",
"libc",
"libc-print",
]
[[package]]
name = "zeroize"
version = "1.5.7"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"

View File

@ -12,7 +12,6 @@ authors = [
[dependencies]
arg = "0.4.1"
c-main = "1.0.1"
console = "0.15.0"
curl = "0.4.44"
dialoguer = "0.9.0"
@ -23,4 +22,4 @@ serde_json = "1"
tokio = { version = "1", features = ["full"] }
toml = "0.7.3"
xdg = "2.4.1"
yacexits = "0.1.3"
yacexits = { git = "https://git.tebibyte.media/yac/yacexits.git", branch = "c-entry", version = "0.2.0" }

View File

@ -19,9 +19,11 @@
* Hopper. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::HopError;
use std::{
fs::File,
io::{Read, self},
io::{ Read, self },
path::PathBuf,
};
@ -32,8 +34,6 @@ use yacexits::{
EX_UNAVAILABLE,
};
use crate::error::CError;
#[derive(Deserialize)]
pub struct Config {
pub hopfiles: Vec<String>,
@ -46,52 +46,103 @@ pub struct Sources {
}
pub enum ConfigError {
CreateFailed(io::Error),
CreateError(io::Error),
OpenError(io::Error),
ReadError(io::Error),
FormatError(std::string::FromUtf8Error),
ParseError(toml::de::Error),
}
impl CError for ConfigError {
fn message(&self) -> String {
match self {
Self::CreateFailed(err) => {
format!("Unable to create configuration file: {}", err)
impl From<ConfigError> for HopError {
fn from(error: ConfigError) -> Self {
let (message, code) = match error {
ConfigError::CreateError(err) => {
(
format!("{}: Unable to create configuration file.", err),
EX_UNAVAILABLE,
)
},
Self::OpenError(err) => {
format!("Unable to open configuration file: {}", err)
ConfigError::OpenError(err) => {
(
format!("{}: Unable to open configuration file.", err),
EX_UNAVAILABLE,
)
},
Self::ReadError(err) => {
format!("Error while reading configuration file: {}", err)
ConfigError::ReadError(err) => {
(
format!("{}: Error while reading configuration file", err),
EX_DATAERR,
)
},
Self::FormatError(err) => {
format!("Configuration file is not valid utf-8: {}", err)
ConfigError::FormatError(err) => {
(
format!("{}: Configuration file is not valid UTF-8.", err),
EX_DATAERR
)
},
Self::ParseError(err) => {
format!("Unable to parse configuration file: {}", err)
ConfigError::ParseError(err) => {
(
format!("{}: Unable to parse configuration file.", err),
EX_DATAERR,
)
},
}
}
};
fn code(&self) -> u32 {
match self {
Self::CreateFailed(_) => EX_UNAVAILABLE,
Self::OpenError(_) => EX_UNAVAILABLE,
Self::ReadError(_) => EX_DATAERR,
Self::FormatError(_) => EX_DATAERR,
Self::ParseError(_) => EX_DATAERR,
}
Self { message, code }
}
}
pub fn get_config(dirs: BaseDirectories) -> Result<PathBuf, ConfigError> {
dirs.place_config_file("config.toml").map_err(ConfigError::CreateFailed)
impl From<ConfigError> for (String, u32) {
fn from(error: ConfigError) -> Self {
let (message, code) = match error {
ConfigError::CreateError(err) => {
(
format!("{}: Unable to create configuration file.", err),
EX_UNAVAILABLE,
)
},
ConfigError::OpenError(err) => {
(
format!("{}: Unable to open configuration file.", err),
EX_UNAVAILABLE,
)
},
ConfigError::ReadError(err) => {
(
format!("{}: Error while reading configuration file", err),
EX_DATAERR,
)
},
ConfigError::FormatError(err) => {
(
format!("{}: Configuration file is not valid UTF-8.", err),
EX_DATAERR
)
},
ConfigError::ParseError(err) => {
(
format!("{}: Unable to parse configuration file", err),
EX_DATAERR,
)
},
};
(message, code)
}
}
impl From<xdg::BaseDirectoriesError> for ConfigError {
fn from(err: xdg::BaseDirectoriesError) -> Self {
ConfigError::CreateError(io::Error::from(err))
}
}
impl Config {
pub fn read_config(config_path: PathBuf) -> Result<Self, ConfigError> {
pub fn read_config() -> Result<Self, ConfigError> {
let config_path = BaseDirectories::with_prefix("hopper")?
.place_config_file("config.toml")
.map_err(ConfigError::CreateError)?;
let mut buf: Vec<u8> = Vec::new();
let mut config_file = File::open(&config_path)

View File

@ -18,48 +18,38 @@
use yacexits::*;
pub trait CError {
fn code(&self) -> u32;
pub struct HopError {
pub code: u32,
fn message(&self) -> String;
fn exit(&self) -> ! {
eprintln!("{}: {}", program_invokation(), self.message());
exit(self.code());
}
pub message: String,
}
fn program_invokation() -> String {
// TODO: ideally this would be argv[0] from main.
// This could be done with a const OnceCell, but I'm not sure I like that solution.
// Using std, we can do this though:
std::env::args().next()
// with a fallback to the program name
.unwrap_or_else(|| env!("CARGO_PKG_NAME").to_owned())
}
impl<'l> CError for arg::ParseKind<'l> {
fn message(&self) -> String {
format!(
"Usage: {}{}",
program_invokation(), // argv[0],
" [-v] add | get | init | list | remove | update\n\n".to_owned() +
impl From<arg::ParseKind<'_>> for HopError {
fn from(_: arg::ParseKind) -> Self {
let message = format!(
"Usage: {}",
"[-v] add | get | init | list | remove | update\n\n".to_owned() +
"add [-m version] [-f hopfiles...] packages...\n" +
"get [-n] [-d directory] [-m versions...] [-t types...] packages\n" +
"init [-f hopfiles...] version type\n" +
"list [[-f hopfiles...] | [-m versions...] [-t types...]]\n" +
"remove [[-f hopfiles...] | type version]] packages...\n" +
"update [[-f hopfiles... | [-m versions...] [-t types...]]",
)
);
Self { message, code: EX_USAGE }
}
fn code(&self) -> u32 { EX_USAGE }
}
impl CError for xdg::BaseDirectoriesError {
fn message(&self) -> String {
format!("Unable to open configuration file: {}", self)
}
impl From<xdg::BaseDirectoriesError> for HopError {
fn from(err: xdg::BaseDirectoriesError) -> Self {
let message = format!("{}: Unable to open configuration file", err);
fn code(&self) -> u32 { EX_UNAVAILABLE }
}
Self { message, code: EX_UNAVAILABLE }
}
}
impl From<HopError> for (String, u32) {
fn from(err: HopError) -> Self {
(err.message, err.code)
}
}

View File

@ -36,7 +36,8 @@ use hopfile::*;
use error::*;
use yacexits::{
exit,
exit,
EX_OSERR,
EX_SOFTWARE,
};
@ -47,34 +48,30 @@ struct AppContext {
#[tokio::main]
#[no_mangle]
async fn rust_main(arguments: c_main::Args) {
async fn rust_main(arguments: yacexits::Args) -> Result<u32, (String, u32)> {
let argv: Vec<&str> = arguments.into_iter().collect();
let args = Arguments::from_args(
argv
.clone()
.into_iter()
).unwrap_or_else(|e| e.exit());
let args = match Arguments::from_args(argv.clone().into_iter()) {
Ok(args) => args,
Err(_) => {
return Err((format!("Unable to ascertain arguments."), EX_OSERR));
}
};
let xdg_basedirs = xdg::BaseDirectories::with_prefix("hopper")
.unwrap_or_else(|e| e.exit());
let config = get_config(xdg_basedirs)
.and_then(Config::read_config)
.unwrap_or_else(|e| e.exit());
let config = Config::read_config()?;
let ctx = AppContext { args, config };
match ctx.args.sub {
// Command::Get(search_args) => cmd_get(&ctx, search_args).await,
// Command::Init(hopfile_args) => cmd_init(hopfile_args).await,
_ => {
eprintln!(
"{}: {}: Unimplemented subcommand.",
argv[0],
ctx.args.sub
);
exit(EX_SOFTWARE);
return Err((
format!(
"{}: Unimplemented subcommand.",
ctx.args.sub
),
EX_SOFTWARE,
));
},
};
}