updated error types
This commit is contained in:
parent
623d65be0d
commit
3eedea2f9c
|
@ -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"
|
||||
|
|
|
@ -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" }
|
||||
|
|
113
src/config.rs
113
src/config.rs
|
@ -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)
|
||||
|
|
54
src/error.rs
54
src/error.rs
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
37
src/main.rs
37
src/main.rs
|
@ -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,
|
||||
));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue