Improve error handling with anyhow
This commit is contained in:
parent
6c2f601300
commit
33eb0c71f8
|
@ -63,6 +63,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assign"
|
name = "assign"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
@ -1218,6 +1224,7 @@ dependencies = [
|
||||||
name = "mxadm"
|
name = "mxadm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"directories",
|
"directories",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|
|
@ -15,3 +15,4 @@ serde = "1.0"
|
||||||
serde-lexpr = "0.1.0"
|
serde-lexpr = "0.1.0"
|
||||||
directories = "3.0"
|
directories = "3.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
anyhow = "1.0.41"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use anyhow::{Context, Result};
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
ruma::{api::client::r0::alias, RoomAliasId, RoomId, UserId},
|
ruma::{api::client::r0::alias, RoomAliasId, RoomId, UserId},
|
||||||
Client, Session, SyncSettings,
|
Client, Session, SyncSettings,
|
||||||
|
@ -8,7 +9,7 @@ use std::io::{self, Write};
|
||||||
|
|
||||||
use crate::session::{build_client_config, restore_session, save_session};
|
use crate::session::{build_client_config, restore_session, save_session};
|
||||||
|
|
||||||
type CommandResult = Result<(), Box<dyn std::error::Error>>;
|
type CommandResult = Result<()>;
|
||||||
|
|
||||||
macro_rules! room_fmt {
|
macro_rules! room_fmt {
|
||||||
() => {
|
() => {
|
||||||
|
@ -18,7 +19,8 @@ macro_rules! room_fmt {
|
||||||
|
|
||||||
pub async fn login(username: Option<&str>) -> CommandResult {
|
pub async fn login(username: Option<&str>) -> CommandResult {
|
||||||
let user_id = match username {
|
let user_id = match username {
|
||||||
Some(s) => UserId::try_from(s)?,
|
Some(s) => UserId::try_from(s)
|
||||||
|
.with_context(|| format!("Failed to parse '{}' as User ID", username))?,
|
||||||
None => {
|
None => {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
|
|
||||||
|
@ -27,17 +29,20 @@ pub async fn login(username: Option<&str>) -> CommandResult {
|
||||||
|
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
stdin.read_line(&mut s)?;
|
stdin.read_line(&mut s)?;
|
||||||
UserId::try_from(s.trim_end())?
|
UserId::try_from(s.trim_end())
|
||||||
|
.with_context(|| format!("Failed to parse '{}' as User ID", s))?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let password = prompt_password_stderr("Password: ")?;
|
let password = prompt_password_stderr("Password: ")?;
|
||||||
|
|
||||||
let client =
|
let client = Client::new_from_user_id_with_config(user_id.clone(), build_client_config())
|
||||||
Client::new_from_user_id_with_config(user_id.clone(), build_client_config()).await?;
|
.await
|
||||||
|
.context("Unable to initialise client")?;
|
||||||
let response = client
|
let response = client
|
||||||
.login(user_id.localpart(), &password, None, Some("mxadm"))
|
.login(user_id.localpart(), &password, None, Some("mxadm"))
|
||||||
.await?;
|
.await
|
||||||
|
.context("Login failed")?;
|
||||||
println!(
|
println!(
|
||||||
"{} logged in? {}",
|
"{} logged in? {}",
|
||||||
client.homeserver().await,
|
client.homeserver().await,
|
||||||
|
@ -81,7 +86,10 @@ pub async fn list_rooms() -> CommandResult {
|
||||||
|
|
||||||
print!("Syncing...");
|
print!("Syncing...");
|
||||||
io::stderr().flush().unwrap();
|
io::stderr().flush().unwrap();
|
||||||
client.sync_once(sync_settings).await?;
|
client
|
||||||
|
.sync_once(sync_settings)
|
||||||
|
.await
|
||||||
|
.context("Sync failed")?;
|
||||||
println!(" done");
|
println!(" done");
|
||||||
|
|
||||||
println!("Joined rooms:");
|
println!("Joined rooms:");
|
||||||
|
@ -100,8 +108,10 @@ pub async fn list_rooms() -> CommandResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_alias(room_id: &str, alias: &str) -> CommandResult {
|
pub async fn add_alias(room_id: &str, alias: &str) -> CommandResult {
|
||||||
let room_id = RoomId::try_from(room_id)?;
|
let room_id = RoomId::try_from(room_id)
|
||||||
let alias_id = RoomAliasId::try_from(alias)?;
|
.with_context(|| format!("Failed to parse '{}' as room ID", room_id))?;
|
||||||
|
let alias_id = RoomAliasId::try_from(alias)
|
||||||
|
.with_context(|| format!("Failed to parse '{}' as room alias", alias))?;
|
||||||
let client = restore_session().await?;
|
let client = restore_session().await?;
|
||||||
|
|
||||||
let request = alias::create_alias::Request::new(&alias_id, &room_id);
|
let request = alias::create_alias::Request::new(&alias_id, &room_id);
|
||||||
|
@ -111,11 +121,15 @@ pub async fn add_alias(room_id: &str, alias: &str) -> CommandResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn del_alias(alias: &str) -> CommandResult {
|
pub async fn del_alias(alias: &str) -> CommandResult {
|
||||||
let alias_id = RoomAliasId::try_from(alias)?;
|
let alias_id = RoomAliasId::try_from(alias)
|
||||||
|
.with_context(|| format!("Failed to parse '{}' as room alias", alias))?;
|
||||||
let client = restore_session().await?;
|
let client = restore_session().await?;
|
||||||
|
|
||||||
let request = alias::delete_alias::Request::new(&alias_id);
|
let request = alias::delete_alias::Request::new(&alias_id);
|
||||||
client.send(request, None).await?;
|
client
|
||||||
|
.send(request, None)
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("Failed to delete alias '{}'", alias))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,17 @@
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate anyhow;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod session;
|
mod session;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
use clap::{App, SubCommand};
|
use clap::{App, SubCommand};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<()> {
|
||||||
let matches = App::new(crate_name!())
|
let matches = App::new(crate_name!())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
|
@ -55,7 +58,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
("del-alias", Some(submatches)) => {
|
("del-alias", Some(submatches)) => {
|
||||||
commands::del_alias(submatches.value_of("alias").unwrap()).await?
|
commands::del_alias(submatches.value_of("alias").unwrap()).await?
|
||||||
}
|
}
|
||||||
("", None) => eprintln!("No subcommand given"),
|
("", None) => bail!("No subcommand given"),
|
||||||
(c, _) => {
|
(c, _) => {
|
||||||
todo!("Subcommand '{}' not implemented yet!", c);
|
todo!("Subcommand '{}' not implemented yet!", c);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
use anyhow::{Context, Result};
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
use matrix_sdk::{Client, ClientConfig, Session};
|
use matrix_sdk::{Client, ClientConfig, Session};
|
||||||
use serde_lexpr;
|
use serde_lexpr;
|
||||||
use std::fs::{create_dir_all, File};
|
use std::fs::{create_dir_all, File};
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PROJECT_DIRS: ProjectDirs = ProjectDirs::from("me", "petrichor", "mxadm")
|
static ref PROJECT_DIRS: ProjectDirs = ProjectDirs::from("me", "petrichor", "mxadm")
|
||||||
|
@ -13,18 +15,25 @@ pub fn build_client_config() -> ClientConfig {
|
||||||
ClientConfig::new().store_path(PROJECT_DIRS.cache_dir().join("store"))
|
ClientConfig::new().store_path(PROJECT_DIRS.cache_dir().join("store"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_session(session: Session) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn save_session(session: Session) -> Result<()> {
|
||||||
let cache_dir = PROJECT_DIRS.cache_dir();
|
let cache_dir = PROJECT_DIRS.cache_dir();
|
||||||
if !cache_dir.exists() {
|
if !cache_dir.exists() {
|
||||||
create_dir_all(cache_dir)?;
|
create_dir_all(cache_dir)
|
||||||
|
.with_context(|| format!("Failed to create cache directory {}", cache_dir.display()))?;
|
||||||
}
|
}
|
||||||
let mut session_file = File::create(cache_dir.join(SESSION_FILE))?;
|
let mut session_file = File::create(cache_dir.join(SESSION_FILE))?;
|
||||||
serde_lexpr::to_writer(&mut session_file, &session)?;
|
serde_lexpr::to_writer(&mut session_file, &session)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn restore_session() -> Result<Client, Box<dyn std::error::Error>> {
|
pub async fn restore_session() -> Result<Client> {
|
||||||
let session_file = File::open(PROJECT_DIRS.cache_dir().join(SESSION_FILE))?;
|
let session_file = match File::open(PROJECT_DIRS.cache_dir().join(SESSION_FILE)) {
|
||||||
|
Err(e) => match e.kind() {
|
||||||
|
ErrorKind::NotFound => bail!("Session file not found: try `mxadm login` first"),
|
||||||
|
_ => return Err(e).context("Unable to open session file"),
|
||||||
|
},
|
||||||
|
Ok(f) => f,
|
||||||
|
};
|
||||||
let session_info: Session = serde_lexpr::from_reader(session_file)?;
|
let session_info: Session = serde_lexpr::from_reader(session_file)?;
|
||||||
|
|
||||||
let client =
|
let client =
|
||||||
|
|
Loading…
Reference in New Issue