switch from using eyre prototype to actual eyre (#1)

- add ci
- update docs
- set default lints
- bump version for new release
This commit is contained in:
Jane Lusby 2020-05-18 08:28:02 -07:00 committed by GitHub
parent 92577f7fef
commit 01e30fd4d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 239 additions and 87 deletions

121
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,121 @@
on:
push:
branches:
- master
pull_request: {}
name: Continuous integration
jobs:
check:
name: Check
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- uses: actions-rs/cargo@v1
with:
command: check
test-features:
name: Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- uses: actions-rs/cargo@v1
with:
command: test
- uses: actions-rs/cargo@v1
with:
command: test
args: --all-features
- uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features
test-versions:
name: Test Suite
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- beta
- nightly
- 1.39.0
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- uses: actions-rs/cargo@v1
with:
command: test
test-os:
name: Test Suite
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
profile: minimal
- uses: actions-rs/cargo@v1
with:
command: test
fmt:
name: Rustfmt
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add clippy
- uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-targets --all-features -- -D warnings

View File

@ -1,6 +1,6 @@
[package] [package]
name = "simple-eyre" name = "simple-eyre"
version = "0.1.0" version = "0.2.0"
authors = ["Jane Lusby <jlusby@yaah.dev>"] authors = ["Jane Lusby <jlusby@yaah.dev>"]
edition = "2018" edition = "2018"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
@ -10,12 +10,9 @@ homepage = "https://github.com/yaahc/simple-eyre"
documentation = "https://docs.rs/simple-eyre" documentation = "https://docs.rs/simple-eyre"
keywords = ["error"] keywords = ["error"]
description = """ description = """
One of the simplest error types one can build ontop of eyre, including only an One of the simplest error reporters one can build ontop of eyre, defining only an error report
inner error boxed as a trait object and a context with only a Backtrace
""" """
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
eyre-impl = "0.1.0" eyre = "0.4.2"
thiserror = "1.0.10" indenter = "0.3.0"

View File

@ -4,9 +4,14 @@ Simple-Eyre
[![Latest Version](https://img.shields.io/crates/v/simple-eyre.svg)](https://crates.io/crates/simple-eyre) [![Latest Version](https://img.shields.io/crates/v/simple-eyre.svg)](https://crates.io/crates/simple-eyre)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/simple-eyre) [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/simple-eyre)
This library provides a custom [`eyre::EyreContext`] type for usage with
[`eyre`] that provides a minimal error report with no additional context.
Essentially the minimal implementation of an error reporter.
```toml ```toml
[dependencies] [dependencies]
simple-eyre = "0.1" eyre = "0.4"
simple-eyre = "0.2"
``` ```
<br> <br>
@ -14,22 +19,18 @@ simple-eyre = "0.1"
## Example ## Example
```rust ```rust
fn eyre::ErrReport; use eyre::{eyre, WrapErr};
use simple_eyre::Report;
fn find_git_root() -> Result<PathBuf, ErrReport> { fn main() -> Result<(), Report> {
find_dir_in_ancestors(".git")?; let e: Report = eyre!("oh no this program is just bad!");
Err(e).wrap_err("usage example successfully experienced a failure")
} }
``` ```
<br> <br>
## Details
- This library is meant to be used as a minimal example of how to use
`eyre-impl`. It implements the absolute minimum necessary to function as a
dynamic error wrapper that associates some context with it. In this case the
context is only a Backtrace.
<br> <br>
#### License #### License
@ -47,6 +48,5 @@ for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions. be dual licensed as above, without any additional terms or conditions.
</sub> </sub>
[`eyre::EyreContext`]: https://docs.rs/eyre/*/eyre/trait.EyreContext.html
[`eyre`]: https://docs.rs/eyre

View File

@ -1,82 +1,116 @@
#![feature(backtrace)] //! This library provides a custom [`eyre::EyreContext`] type for usage with [`eyre`] that provides
use eyre_impl::{ErrorReporter, Indented}; //! a minimal error report with no additional context. Essentially the minimal implementation of an
use std::backtrace::{Backtrace, BacktraceStatus}; //! error reporter.
use std::fmt::{self, Write as _}; //!
//! # Example
//!
//! ```rust,should_panic
//! use eyre::{eyre, WrapErr};
//! use simple_eyre::Report;
//!
//! fn main() -> Result<(), Report> {
//! let e: Report = eyre!("oh no this program is just bad!");
//!
//! Err(e).wrap_err("usage example successfully experienced a failure")
//! }
//! ```
//!
//! [`eyre::EyreContext`]: https://docs.rs/eyre/*/eyre/trait.EyreContext.html
//! [`eyre`]: https://docs.rs/eyre
#![doc(html_root_url = "https://docs.rs/simple-eyre/0.2.0")]
#![warn(
missing_debug_implementations,
missing_docs,
missing_doc_code_examples,
rust_2018_idioms,
unreachable_pub,
bad_style,
const_err,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
private_in_public,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true
)]
use eyre::Chain;
use eyre::EyreContext;
use indenter::indented;
use std::error::Error;
/// A custom context type for minimal error reporting via `eyre`
#[derive(Debug)] #[derive(Debug)]
pub struct BoxError(Box<dyn std::error::Error + Send + Sync + 'static>); pub struct Context;
impl std::error::Error for BoxError { impl EyreContext for Context {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { #[allow(unused_variables)]
self.0.source() fn default(error: &(dyn Error + 'static)) -> Self {
Self
} }
}
impl fmt::Display for BoxError { fn debug(
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { &self,
fmt::Display::fmt(&self.0, f) error: &(dyn Error + 'static),
} f: &mut core::fmt::Formatter<'_>,
} ) -> core::fmt::Result {
use core::fmt::Write as _;
pub struct Context {
backtrace: Backtrace,
}
impl Default for Context {
fn default() -> Self {
Self {
backtrace: Backtrace::capture(),
}
}
}
pub struct ErrReport(ErrorReporter<BoxError, Context>);
impl<E> From<E> for ErrReport
where
E: std::error::Error + Send + Sync + 'static,
{
fn from(err: E) -> Self {
ErrReport(ErrorReporter::from(BoxError(Box::new(err))))
}
}
impl fmt::Debug for ErrReport {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let error = &self.0.error;
if f.alternate() { if f.alternate() {
return fmt::Debug::fmt(error, f); return core::fmt::Debug::fmt(error, f);
} }
let errors = self.0.chain().rev().enumerate(); write!(f, "{}", error)?;
writeln!(f)?; if let Some(cause) = error.source() {
write!(f, "\n\nCaused by:")?;
for (n, error) in errors { let multiple = cause.source().is_some();
write!(Indented::numbered(f, n), "{}", error)?; for (n, error) in Chain::new(cause).enumerate() {
writeln!(f)?; writeln!(f)?;
} if multiple {
write!(indented(f).ind(n), "{}", error)?;
let backtrace = &self.0.context.backtrace; } else {
if let BacktraceStatus::Captured = backtrace.status() { write!(indented(f), "{}", error)?;
write!(f, "\n\n{}", backtrace)?; }
}
Ok(())
}
}
impl fmt::Display for ErrReport {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0.error)?;
if f.alternate() {
for cause in self.0.chain().skip(1) {
write!(f, ": {}", cause)?;
} }
} }
Ok(()) Ok(())
} }
} }
/// A type alias for `eyre::Report<simple_eyre::Context>`
///
/// # Example
///
/// ```rust
/// use simple_eyre::Report;
///
/// # struct Config;
/// fn try_thing(path: &str) -> Result<Config, Report> {
/// // ...
/// # Ok(Config)
/// }
/// ```
pub type Report = eyre::Report<Context>;
/// A type alias for `Result<T, simple_eyre::Report>`
///
/// # Example
///
///```
/// fn main() -> simple_eyre::Result<()> {
///
/// // ...
///
/// Ok(())
/// }
/// ```
pub type Result<T, E = Report> = core::result::Result<T, E>;