Skip to content
This repository was archived by the owner on Feb 28, 2021. It is now read-only.

cli: use thiserror for CommandError Display #317

Merged
merged 3 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions cli/src/account_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,37 @@ type Seed = [u8; 32];

#[derive(Debug, ThisError)]
pub enum Error {
/// An Account with the given name already exists
/// An account with the given name already exists
#[error("An account with the given name already exists")]
AlreadyExists(),

/// An IOError occurred
#[error("An IO error occured: {0}")]
IOError(IOError),
/// Failed to write to the accounts file
#[error("Failed to write to the accounts file: {0}")]
FailedWrite(#[from] WritingError),

/// A serde json Error occurred
#[error("A serde json error occured: {0}")]
JsonError(serde_json::Error),
/// Failed to read the accounts file
#[error("Failed to read the accounts file: {0}")]
FailedRead(#[from] ReadingError),
}

/// Possible errors when writing to the accounts file.
#[derive(Debug, ThisError)]
pub enum WritingError {
#[error(transparent)]
IO(IOError),

#[error(transparent)]
Serialization(serde_json::Error),
}

/// Possible errors when reading the accounts file.
#[derive(Debug, ThisError)]
pub enum ReadingError {
#[error(transparent)]
IO(IOError),

#[error(transparent)]
Deserialization(serde_json::Error),
}

/// Add an account to the storage.
Expand All @@ -66,21 +86,22 @@ pub fn add(name: String, data: AccountData) -> Result<(), Error> {
update(accounts)
}

/// List all the stored accounts
/// List all the stored accounts.
///
/// It can fail from IO and Serde Json errors.
pub fn list() -> Result<HashMap<String, AccountData>, Error> {
let path_buf = get_or_create_path()?;
let file = File::open(path_buf.as_path()).map_err(Error::IOError)?;
let file = File::open(path_buf.as_path()).map_err(ReadingError::IO)?;
let accounts: HashMap<String, AccountData> =
serde_json::from_reader(&file).map_err(Error::JsonError)?;
serde_json::from_reader(&file).map_err(ReadingError::Deserialization)?;
Ok(accounts)
}

fn update(accounts: HashMap<String, AccountData>) -> Result<(), Error> {
let path_buf = get_or_create_path()?;
let new_content = serde_json::to_string(&accounts).map_err(Error::JsonError)?;
std::fs::write(path_buf.as_path(), new_content.as_bytes()).map_err(Error::IOError)
let new_content = serde_json::to_string(&accounts).map_err(WritingError::Serialization)?;
std::fs::write(path_buf.as_path(), new_content.as_bytes()).map_err(WritingError::IO)?;
Ok(())
}

const FILE: &str = "accounts.json";
Expand All @@ -96,7 +117,7 @@ fn get_or_create_path() -> Result<PathBuf, Error> {
let path = path_buf.as_path();

if !path.exists() {
std::fs::write(path, b"{}").map_err(Error::IOError)?
std::fs::write(path, b"{}").map_err(WritingError::IO)?;
}

Ok(path_buf)
Expand All @@ -107,6 +128,6 @@ fn dir() -> Result<PathBuf, Error> {
.unwrap()
.data_dir()
.join("radicle-registry-cli");
std::fs::create_dir_all(&dir).map_err(Error::IOError)?;
std::fs::create_dir_all(&dir).map_err(ReadingError::IO)?;
Ok(dir)
}
40 changes: 14 additions & 26 deletions cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use radicle_registry_client::*;
use structopt::StructOpt;
use thiserror::Error as ThisError;

pub mod account_storage;

Expand Down Expand Up @@ -118,40 +119,27 @@ pub trait CommandT {

/// Error returned by [CommandT::run].
///
/// Implements [From] for client errors.
#[derive(Debug, derive_more::From)]
/// Implements [From] for client errors and [account_storage] errors.
#[derive(Debug, ThisError)]
pub enum CommandError {
ClientError(Error),
#[error("Client error: {0}")]
ClientError(#[from] Error),

#[error("Transaction {tx_hash} failed in block {block_hash}")]
FailedTransaction {
tx_hash: TxHash,
block_hash: BlockHash,
},
OrgNotFound {
org_id: OrgId,
},

#[error("Cannot find org {org_id}")]
OrgNotFound { org_id: OrgId },

#[error("Cannot find project {project_name}.{org_id}")]
ProjectNotFound {
project_name: ProjectName,
org_id: OrgId,
},
AccountStorageError(account_storage::Error),
}

impl core::fmt::Display for CommandError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
CommandError::ClientError(error) => write!(f, "Client error: {}", error),
CommandError::FailedTransaction {
tx_hash,
block_hash,
} => write!(f, "Transaction {} failed in block {}", tx_hash, block_hash),
CommandError::OrgNotFound { org_id } => write!(f, "Cannot find org {}", org_id),
CommandError::ProjectNotFound {
project_name,
org_id,
} => write!(f, "Cannot find project {}.{}", project_name, org_id),
CommandError::AccountStorageError(error) => {
write!(f, "Account storage error: {}", error)
}
}
}
#[error("{0}")]
AccountStorageError(#[from] account_storage::Error),
}