rust: Add and use fn-error-context

Same motivation as https://github.com/coreos/bootupd/pull/163

Effectively what we're doing here is creating a human-readable subset
of the stack trace. This is nicer than having the calling functions
add with_context() because it's more verbose (gets duplicative at
each call site), easy to forget, etc.
This commit is contained in:
Colin Walters 2021-03-09 19:01:35 +00:00 committed by OpenShift Merge Robot
parent 1dc7503838
commit 95ff12b913
7 changed files with 29 additions and 8 deletions

12
Cargo.lock generated
View File

@ -324,6 +324,17 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "fn-error-context"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac0b92c51c8b8183a0c101a7b2ea5fac11d2f1e01057f91e390284c75d76ef44"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "foreign-types" name = "foreign-types"
version = "0.5.0" version = "0.5.0"
@ -1203,6 +1214,7 @@ dependencies = [
"curl", "curl",
"cxx", "cxx",
"envsubst", "envsubst",
"fn-error-context",
"gio", "gio",
"gio-sys", "gio-sys",
"glib", "glib",

View File

@ -32,6 +32,7 @@ clap = "2.33.3"
curl = "0.4.34" curl = "0.4.34"
cxx = "1.0.32" cxx = "1.0.32"
envsubst = "0.2.0" envsubst = "0.2.0"
fn-error-context = "0.1.1"
gio = "0.9.1" gio = "0.9.1"
gio-sys = "0.10.1" gio-sys = "0.10.1"
gobject-sys = "0.10.0" gobject-sys = "0.10.0"

View File

@ -161,18 +161,21 @@ mod err {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use fn_error_context::context;
#[test] #[test]
fn throwchain() { fn throwchain() {
use anyhow::Context; use anyhow::Context;
fn outer() -> CxxResult<()> { fn outer() -> CxxResult<()> {
#[context("inner")]
fn inner() -> anyhow::Result<()> { fn inner() -> anyhow::Result<()> {
anyhow::bail!("inner") anyhow::bail!("oops")
} }
Ok(inner().context("Failed in outer")?) Ok(inner().context("Failed in outer")?)
} }
assert_eq!( assert_eq!(
format!("{}", outer().err().unwrap()), format!("{}", outer().err().unwrap()),
"Failed in outer: inner" "Failed in outer: inner: oops"
) )
} }
} }

View File

@ -6,7 +6,8 @@
//! Compute difference between two filesystem trees. //! Compute difference between two filesystem trees.
use anyhow::{Context, Result}; use anyhow::Result;
use fn_error_context::context;
use openat_ext::OpenatDirExt; use openat_ext::OpenatDirExt;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow; use std::borrow::Cow;
@ -204,11 +205,12 @@ fn diff_recurse(
} }
/// Given two directories, compute the diff between them. /// Given two directories, compute the diff between them.
#[context("Computing filesystem diff")]
pub(crate) fn diff(src: &openat::Dir, dest: &openat::Dir) -> Result<Diff> { pub(crate) fn diff(src: &openat::Dir, dest: &openat::Dir) -> Result<Diff> {
let mut diff = Diff { let mut diff = Diff {
..Default::default() ..Default::default()
}; };
diff_recurse(None, src, dest, &mut diff).context("Failed to compute fsdiff")?; diff_recurse(None, src, dest, &mut diff)?;
Ok(diff) Ok(diff)
} }

View File

@ -35,7 +35,8 @@
// (FIXME: Convert to Apache-2.0 OR MIT for consistency?) // (FIXME: Convert to Apache-2.0 OR MIT for consistency?)
use crate::cxxrsutil::*; use crate::cxxrsutil::*;
use crate::ffi::HistoryEntry; use crate::ffi::HistoryEntry;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Result};
use fn_error_context::context;
use openat::{self, Dir, SimpleType}; use openat::{self, Dir, SimpleType};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs; use std::fs;
@ -176,6 +177,7 @@ fn history_get_oldest_deployment_msg_timestamp() -> Result<Option<u64>> {
/// Gets the oldest deployment message in the journal, and nuke all the GVariant data files /// Gets the oldest deployment message in the journal, and nuke all the GVariant data files
/// that correspond to deployments older than that one. Essentially, this binds pruning to /// that correspond to deployments older than that one. Essentially, this binds pruning to
/// journal pruning. /// journal pruning.
#[context("Failed to prune history")]
fn history_prune_inner() -> Result<()> { fn history_prune_inner() -> Result<()> {
if !Path::new(RPMOSTREE_HISTORY_DIR).exists() { if !Path::new(RPMOSTREE_HISTORY_DIR).exists() {
return Ok(()); return Ok(());
@ -211,7 +213,7 @@ fn history_prune_inner() -> Result<()> {
} }
pub(crate) fn history_prune() -> CxxResult<()> { pub(crate) fn history_prune() -> CxxResult<()> {
Ok(history_prune_inner().context("Failed to prune history")?) Ok(history_prune_inner()?)
} }
pub(crate) fn history_ctx_new() -> CxxResult<Box<HistoryCtx>> { pub(crate) fn history_ctx_new() -> CxxResult<Box<HistoryCtx>> {

View File

@ -439,8 +439,7 @@ pub(crate) fn transaction_apply_live(
.filter(|s| !s.is_empty()) .filter(|s| !s.is_empty())
.unwrap_or(booted_commit); .unwrap_or(booted_commit);
// Compute the filesystem-level diff // Compute the filesystem-level diff
let diff = crate::ostree_diff::diff(repo, source_commit, &target_commit, Some("/usr")) let diff = crate::ostree_diff::diff(repo, source_commit, &target_commit, Some("/usr"))?;
.context("Failed computing diff")?;
// And then the package-level diff // And then the package-level diff
let pkgdiff = { let pkgdiff = {
cxx::let_cxx_string!(from = source_commit); cxx::let_cxx_string!(from = source_commit);

View File

@ -7,6 +7,7 @@
*/ */
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use fn_error_context::context;
use gio::prelude::*; use gio::prelude::*;
use ostree::RepoFileExt; use ostree::RepoFileExt;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
@ -149,6 +150,7 @@ fn diff_recurse(
} }
/// Given two ostree commits, compute the diff between them. /// Given two ostree commits, compute the diff between them.
#[context("Computing ostree diff")]
pub(crate) fn diff<P: AsRef<str>>( pub(crate) fn diff<P: AsRef<str>>(
repo: &ostree::Repo, repo: &ostree::Repo,
from: &str, from: &str,