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]
name = "simple-eyre"
version = "0.1.0"
version = "0.2.0"
authors = ["Jane Lusby <jlusby@yaah.dev>"]
edition = "2018"
license = "MIT OR Apache-2.0"
@ -10,12 +10,9 @@ homepage = "https://github.com/yaahc/simple-eyre"
documentation = "https://docs.rs/simple-eyre"
keywords = ["error"]
description = """
One of the simplest error types one can build ontop of eyre, including only an
inner error boxed as a trait object and a context with only a Backtrace
One of the simplest error reporters one can build ontop of eyre, defining only an error report
"""
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eyre-impl = "0.1.0"
thiserror = "1.0.10"
eyre = "0.4.2"
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)
[![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
[dependencies]
simple-eyre = "0.1"
eyre = "0.4"
simple-eyre = "0.2"
```
<br>
@ -14,22 +19,18 @@ simple-eyre = "0.1"
## Example
```rust
fn eyre::ErrReport;
use eyre::{eyre, WrapErr};
use simple_eyre::Report;
fn find_git_root() -> Result<PathBuf, ErrReport> {
find_dir_in_ancestors(".git")?;
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")
}
```
<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>
#### 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.
</sub>
[`eyre::EyreContext`]: https://docs.rs/eyre/*/eyre/trait.EyreContext.html
[`eyre`]: https://docs.rs/eyre

View File

@ -1,82 +1,116 @@
#![feature(backtrace)]
use eyre_impl::{ErrorReporter, Indented};
use std::backtrace::{Backtrace, BacktraceStatus};
use std::fmt::{self, Write as _};
//! 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.
//!
//! # 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)]
pub struct BoxError(Box<dyn std::error::Error + Send + Sync + 'static>);
pub struct Context;
impl std::error::Error for BoxError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.0.source()
impl EyreContext for Context {
#[allow(unused_variables)]
fn default(error: &(dyn Error + 'static)) -> Self {
Self
}
}
impl fmt::Display for BoxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
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;
fn debug(
&self,
error: &(dyn Error + 'static),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
use core::fmt::Write as _;
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)?;
for (n, error) in errors {
write!(Indented::numbered(f, n), "{}", error)?;
writeln!(f)?;
}
let backtrace = &self.0.context.backtrace;
if let BacktraceStatus::Captured = backtrace.status() {
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)?;
if let Some(cause) = error.source() {
write!(f, "\n\nCaused by:")?;
let multiple = cause.source().is_some();
for (n, error) in Chain::new(cause).enumerate() {
writeln!(f)?;
if multiple {
write!(indented(f).ind(n), "{}", error)?;
} else {
write!(indented(f), "{}", error)?;
}
}
}
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>;