Skip to content

Commit d74e956

Browse files
committed
Switch from anyhow to miette and improve some errs
Signed-off-by: Ryan Bottriell <[email protected]> Add a format Wrapped error variant The previous method mashed strings together, losing any context which we don't want to do. Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Add error doc page and link in diagnostics This will allow us to assign specific error codes and link users to our documentation site with longer form, and supplementary material related to the error and how it might be resolved. Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Add specific error information for mkdir /spfs Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Use miette for errors in spk as well Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Propagate miette usage to windows code Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Attach the path to repository open Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Introduce a local error type OpenRepositoryError This also comes with the MigrationError type, which both work together to refine the set of errors that can happen when opening a repository. This allows each condition to have richer diagnostic information for anyone encountering the error. Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Add spfs init command for making repos Signed-off-by: Ryan Bottriell <[email protected]> Signed-off-by: Ryan Bottriell <[email protected]> Fill in missing error code docs Signed-off-by: Ryan Bottriell <[email protected]> Remove uneccessary use of into_diagnostic Signed-off-by: Ryan Bottriell <[email protected]>
1 parent ebff9ac commit d74e956

File tree

175 files changed

+1492
-599
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

175 files changed

+1492
-599
lines changed

Cargo.lock

+160-29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ edition = "2021"
3333
version = "0.38.0"
3434

3535
[workspace.dependencies]
36-
anyhow = "1.0"
3736
bytes = "1.5"
3837
arc-swap = "1.6.0"
3938
async-trait = "0.1"
@@ -54,6 +53,7 @@ fuser = "0.12"
5453
glob = "0.3"
5554
indicatif = "0.17.5"
5655
libc = "0.2.80"
56+
miette = "5.10"
5757
nix = "0.26.2"
5858
nom = "7.1"
5959
nom-supreme = "0.8"

crates/spfs-cli/cmd-clean/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ path = "src/cmd_clean.rs"
1212
sentry = ["spfs-cli-common/sentry"]
1313

1414
[dependencies]
15-
anyhow = { workspace = true }
1615
chrono = { workspace = true }
1716
clap = { workspace = true }
1817
colored = { workspace = true }
18+
miette = { workspace = true, features = ["fancy"] }
1919
question = "0.2.2"
2020
spfs = { path = "../../spfs" }
2121
spfs-cli-common = { path = "../common" }
2222
tokio = { version = "1.20", features = ["rt", "rt-multi-thread"] }
2323
tracing = { workspace = true }
24-
url = { version = "2.2", features = ["serde"] }
24+
url = { version = "2.2", features = ["serde"] }

crates/spfs-cli/cmd-clean/src/cmd_clean.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77

88
use std::collections::HashSet;
99

10-
use anyhow::Result;
1110
use chrono::prelude::*;
1211
use clap::Parser;
1312
use colored::Colorize;
13+
use miette::Result;
1414
use spfs_cli_common as cli;
1515
use spfs_cli_common::CommandName;
1616

@@ -237,7 +237,7 @@ fn age_to_date(age: &str) -> Result<DateTime<Utc>> {
237237
.parse()
238238
.map_err(|err| spfs::Error::from(format!("{err:?}")))?;
239239
if num < 0 {
240-
anyhow::bail!("provided age must be greater than zero: '{age}'");
240+
miette::bail!("provided age must be greater than zero: '{age}'");
241241
}
242242

243243
match postfix {
@@ -247,6 +247,6 @@ fn age_to_date(age: &str) -> Result<DateTime<Utc>> {
247247
"h" => Ok(Utc::now() - chrono::Duration::hours(num)),
248248
"m" => Ok(Utc::now() - chrono::Duration::minutes(num)),
249249
"s" => Ok(Utc::now() - chrono::Duration::seconds(num)),
250-
_ => anyhow::bail!("Unknown age postfix: '{postfix}', must be one of y, w, d, h, m, s"),
250+
_ => miette::bail!("Unknown age postfix: '{postfix}', must be one of y, w, d, h, m, s"),
251251
}
252252
}

crates/spfs-cli/cmd-enter/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ path = "src/cmd_enter.rs"
1212
sentry = ["spfs-cli-common/sentry"]
1313

1414
[dependencies]
15-
anyhow = { workspace = true }
1615
clap = { workspace = true }
16+
miette = { workspace = true, features = ["fancy"] }
1717
nix = { workspace = true }
1818
spfs = { path = "../../spfs" }
1919
spfs-cli-common = { path = "../common" }

crates/spfs-cli/cmd-enter/src/cmd_enter.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ use std::ffi::OsString;
1010
use std::sync::atomic::Ordering;
1111
use std::time::Instant;
1212

13-
use anyhow::{Context, Result};
1413
use clap::{Args, Parser};
1514
#[cfg(feature = "sentry")]
1615
use cli::configure_sentry;
16+
use miette::{Context, Result};
1717
use spfs::monitor::SPFS_MONITOR_FOREGROUND_LOGGING_VAR;
1818
use spfs::storage::fs::RenderSummary;
1919
use spfs_cli_common as cli;
@@ -222,12 +222,12 @@ impl CmdEnter {
222222
// proceed with using the runtime, so we don't ignore this
223223
// error and hope for the best. Using this new environment
224224
// puts whatever is using it at risk of data loss.
225-
anyhow::bail!(
225+
miette::bail!(
226226
"spfs-monitor disappeared unexpectedly, it is unsafe to continue. Setting ${SPFS_MONITOR_FOREGROUND_LOGGING_VAR}=1 may provide more details"
227227
);
228228
}
229229
Err(err) => {
230-
anyhow::bail!("Failed to inform spfs-monitor to start: {err}");
230+
miette::bail!("Failed to inform spfs-monitor to start: {err}");
231231
}
232232
};
233233

@@ -286,7 +286,7 @@ impl CmdEnter {
286286

287287
cmd.exec()
288288
.map(|_| 0)
289-
.context("Failed to execute runtime command")
289+
.wrap_err("Failed to execute runtime command")
290290
}
291291

292292
#[cfg_attr(not(feature = "sentry"), allow(unused))]

crates/spfs-cli/cmd-fuse/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ fuse-backend-rhel-7-9 = ["spfs-vfs/fuse-backend-rhel-7-9"]
1919
sentry = ["spfs-cli-common/sentry"]
2020

2121
[dependencies]
22-
anyhow = { workspace = true }
2322
clap = { workspace = true }
2423
dashmap = { workspace = true }
2524
spfs-vfs = { path = "../../spfs-vfs" }
26-
nix = { workspace = true, features = ["process"] }
2725
libc = "0.2"
26+
miette = { workspace = true, features = ["fancy"] }
27+
nix = { workspace = true, features = ["process"] }
2828
spfs = { path = "../../spfs", features = ["fuse-backend"] }
2929
spfs-cli-common = { path = "../common" }
3030
tokio = { version = "1.20", features = ["rt", "rt-multi-thread"] }

crates/spfs-cli/cmd-fuse/src/cmd_fuse.rs

+46-26
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// https://github.com/imageworks/spk
44

5-
use anyhow::{anyhow, bail, Context, Result};
65
use clap::Parser;
76
use fuser::MountOption;
7+
use miette::{bail, miette, Context, IntoDiagnostic, Result};
88
use spfs::tracking::EnvSpec;
99
use spfs::Error;
1010
use spfs_cli_common as cli;
@@ -14,13 +14,13 @@ use tokio::signal::unix::{signal, SignalKind};
1414
// The runtime setup process manages the current namespace
1515
// which operates only on the current thread. For this reason
1616
// we must use a single threaded async runtime, if any.
17-
fn main() {
17+
fn main() -> Result<()> {
1818
// because this function exits right away it does not
1919
// properly handle destruction of data, so we put the actual
2020
// logic into a separate function/scope
21-
std::process::exit(main2())
21+
std::process::exit(main2()?)
2222
}
23-
fn main2() -> i32 {
23+
fn main2() -> Result<i32> {
2424
let mut opt = CmdFuse::parse();
2525
opt.logging
2626
.log_file
@@ -31,7 +31,7 @@ fn main2() -> i32 {
3131
let config = match spfs::get_config() {
3232
Err(err) => {
3333
tracing::error!(err = ?err, "failed to load config");
34-
return 1;
34+
return Ok(1);
3535
}
3636
Ok(config) => config,
3737
};
@@ -158,19 +158,27 @@ impl CmdFuse {
158158
let mountpoint = self
159159
.mountpoint
160160
.canonicalize()
161-
.context("Invalid mount point")?;
161+
.into_diagnostic()
162+
.wrap_err("Invalid mount point")?;
162163

163164
if !opts.uid.is_root() {
164-
nix::unistd::seteuid(opts.uid).context("Failed to become desired user (effective)")?;
165-
nix::unistd::setegid(opts.gid).context("Failed to become desired group (effective)")?;
165+
nix::unistd::seteuid(opts.uid)
166+
.into_diagnostic()
167+
.wrap_err("Failed to become desired user (effective)")?;
168+
nix::unistd::setegid(opts.gid)
169+
.into_diagnostic()
170+
.wrap_err("Failed to become desired group (effective)")?;
166171
// unprivileged users must have write access to the directory that
167172
// they are trying to mount over.
168173
nix::unistd::access(&mountpoint, nix::unistd::AccessFlags::W_OK)
169-
.context("Must have write access to mountpoint")?;
174+
.into_diagnostic()
175+
.wrap_err("Must have write access to mountpoint")?;
170176
nix::unistd::seteuid(calling_uid)
171-
.context("Failed to reset calling user (effective)")?;
177+
.into_diagnostic()
178+
.wrap_err("Failed to reset calling user (effective)")?;
172179
nix::unistd::setegid(calling_gid)
173-
.context("Failed to reset calling group (effective)")?;
180+
.into_diagnostic()
181+
.wrap_err("Failed to reset calling group (effective)")?;
174182
}
175183

176184
// establish the fuse session before changing the uid/gid of this process
@@ -184,23 +192,34 @@ impl CmdFuse {
184192
&mountpoint,
185193
&mount_opts,
186194
)
187-
.context("Failed to create a FUSE session")?;
195+
.into_diagnostic()
196+
.wrap_err("Failed to create a FUSE session")?;
188197

189198
if opts.gid != calling_gid {
190-
nix::unistd::setgid(opts.gid).context("Failed to set desired group (actual)")?;
191-
nix::unistd::setegid(opts.gid).context("Failed to set desired group (effective)")?;
199+
nix::unistd::setgid(opts.gid)
200+
.into_diagnostic()
201+
.wrap_err("Failed to set desired group (actual)")?;
202+
nix::unistd::setegid(opts.gid)
203+
.into_diagnostic()
204+
.wrap_err("Failed to set desired group (effective)")?;
192205
}
193206
if opts.uid != calling_uid {
194-
nix::unistd::setuid(opts.uid).context("Failed to become desired user (actual)")?;
195-
nix::unistd::seteuid(opts.uid).context("Failed to become desired user (effective)")?;
207+
nix::unistd::setuid(opts.uid)
208+
.into_diagnostic()
209+
.wrap_err("Failed to become desired user (actual)")?;
210+
nix::unistd::seteuid(opts.uid)
211+
.into_diagnostic()
212+
.wrap_err("Failed to become desired user (effective)")?;
196213
}
197214

198215
if !self.foreground {
199216
tracing::debug!("Moving into background...");
200217
// We cannot daemonize until the session is established above,
201218
// otherwise initial use of the filesystem may not show any mount
202219
// at all.
203-
nix::unistd::daemon(false, self.log_foreground)?;
220+
nix::unistd::daemon(false, self.log_foreground)
221+
.into_diagnostic()
222+
.wrap_err("Failed to daemonize")?;
204223
}
205224

206225
// We also cannot go multi-thread until the daemonization process above
@@ -213,12 +232,13 @@ impl CmdFuse {
213232
.max_blocking_threads(config.fuse.max_blocking_threads.get())
214233
.enable_all()
215234
.build()
216-
.context("Failed to establish runtime")?;
235+
.into_diagnostic()
236+
.wrap_err("Failed to establish runtime")?;
217237

218238
let result = rt.block_on(async move {
219-
let mut interrupt = signal(SignalKind::interrupt()).context("interrupt signal handler")?;
220-
let mut quit = signal(SignalKind::quit()).context("quit signal handler")?;
221-
let mut terminate = signal(SignalKind::terminate()).context("terminate signal handler")?;
239+
let mut interrupt = signal(SignalKind::interrupt()).into_diagnostic().wrap_err("interrupt signal handler")?;
240+
let mut quit = signal(SignalKind::quit()).into_diagnostic().wrap_err("quit signal handler")?;
241+
let mut terminate = signal(SignalKind::terminate()).into_diagnostic().wrap_err("terminate signal handler")?;
222242

223243
tracing::info!("Starting FUSE filesystem");
224244
// Although the filesystem could run in the current thread, we prefer to
@@ -230,13 +250,13 @@ impl CmdFuse {
230250
let res = tokio::select!{
231251
res = join_handle => {
232252
tracing::info!("Filesystem shutting down");
233-
res.context("FUSE session failed")
253+
res.into_diagnostic().wrap_err("FUSE session failed")
234254
}
235255
// we explicitly catch any signal related to interruption
236256
// and will act by shutting down the filesystem early
237-
_ = terminate.recv() => Err(anyhow!("Terminate signal received, filesystem shutting down")),
238-
_ = interrupt.recv() => Err(anyhow!("Interrupt signal received, filesystem shutting down")),
239-
_ = quit.recv() => Err(anyhow!("Quit signal received, filesystem shutting down")),
257+
_ = terminate.recv() => Err(miette!("Terminate signal received, filesystem shutting down")),
258+
_ = interrupt.recv() => Err(miette!("Interrupt signal received, filesystem shutting down")),
259+
_ = quit.recv() => Err(miette!("Quit signal received, filesystem shutting down")),
240260
};
241261
// the filesystem task must be fully terminated in order for the subsequent unmount
242262
// process to function. Otherwise, the background task will keep this process alive
@@ -251,7 +271,7 @@ impl CmdFuse {
251271
// events which will never come and so we don't want to block forever
252272
// when the runtime is dropped.
253273
rt.shutdown_timeout(std::time::Duration::from_secs(2));
254-
result??;
274+
result?.into_diagnostic()?;
255275
Ok(0)
256276
}
257277
}

crates/spfs-cli/cmd-join/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ path = "src/cmd_join.rs"
1212
sentry = ["spfs-cli-common/sentry"]
1313

1414
[dependencies]
15-
anyhow = { workspace = true }
1615
clap = { workspace = true }
1716
futures = { workspace = true }
17+
miette = { workspace = true, features = ["fancy"] }
1818
spfs = { path = "../../spfs" }
1919
spfs-cli-common = { path = "../common" }
2020
tokio = { version = "1.20", features = ["rt", "rt-multi-thread"] }

crates/spfs-cli/cmd-join/src/cmd_join.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
use std::ffi::OsString;
99

10-
use anyhow::{anyhow, bail, Context, Result};
1110
use clap::{ArgGroup, Parser};
1211
use futures::StreamExt;
12+
use miette::{bail, miette, Context, Result};
1313
use spfs::Error;
1414
use spfs_cli_common as cli;
1515
use spfs_cli_common::CommandName;
@@ -62,12 +62,12 @@ impl CmdJoin {
6262
storage
6363
.read_runtime(runtime)
6464
.await
65-
.map_err(Into::<anyhow::Error>::into)
65+
.map_err(Into::<miette::Error>::into)
6666
} else if let Some(pid) = self.pid {
6767
let mount_ns = spfs::monitor::identify_mount_namespace_of_process(pid)
6868
.await
69-
.context("identify mount namespace of pid")?
70-
.ok_or(anyhow!("pid not found"))?;
69+
.wrap_err("identify mount namespace of pid")?
70+
.ok_or(miette!("pid not found"))?;
7171
let mut runtimes = storage.iter_runtimes().await;
7272
while let Some(runtime) = runtimes.next().await {
7373
let Ok(runtime) = runtime else {

crates/spfs-cli/cmd-monitor/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ path = "src/cmd_monitor.rs"
1212
sentry = ["spfs/sentry", "spfs-cli-common/sentry"]
1313

1414
[dependencies]
15-
anyhow = { workspace = true }
1615
clap = { workspace = true }
16+
miette = { workspace = true, features = ["fancy"] }
1717
nix = { workspace = true }
1818
spfs = { path = "../../spfs", features = ["fuse-backend"] }
1919
spfs-cli-common = { path = "../common" }

crates/spfs-cli/cmd-monitor/src/cmd_monitor.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@
77

88
use std::time::Duration;
99

10-
use anyhow::{Context, Result};
1110
use clap::Parser;
1211
#[cfg(feature = "sentry")]
1312
use cli::configure_sentry;
13+
use miette::{Context, IntoDiagnostic, Result};
1414
use spfs::Error;
1515
use spfs_cli_common as cli;
1616
use spfs_cli_common::CommandName;
1717
use tokio::io::AsyncReadExt;
1818
use tokio::signal::unix::{signal, SignalKind};
1919
use tokio::time::timeout;
2020

21-
fn main() {
21+
fn main() -> Result<()> {
2222
// because this function exits right away it does not
2323
// properly handle destruction of data, so we put the actual
2424
// logic into a separate function/scope
25-
std::process::exit(main2())
25+
std::process::exit(main2()?);
2626
}
27-
fn main2() -> i32 {
27+
fn main2() -> Result<i32> {
2828
let mut opt = CmdMonitor::parse();
2929
opt.logging
3030
.log_file
@@ -84,13 +84,15 @@ impl CmdMonitor {
8484
.max_blocking_threads(1)
8585
.enable_all()
8686
.build()
87-
.context("Failed to establish async runtime")?;
87+
.into_diagnostic()
88+
.wrap_err("Failed to establish async runtime")?;
8889
rt.block_on(self.wait_for_ready());
8990
// clean up this runtime and all other threads before detaching
9091
drop(rt);
9192

9293
nix::unistd::daemon(self.no_chdir, self.no_close)
93-
.context("Failed to daemonize the monitor process")?;
94+
.into_diagnostic()
95+
.wrap_err("Failed to daemonize the monitor process")?;
9496

9597
#[cfg(feature = "sentry")]
9698
{
@@ -106,7 +108,8 @@ impl CmdMonitor {
106108
.max_blocking_threads(config.monitor.max_blocking_threads.get())
107109
.enable_all()
108110
.build()
109-
.context("Failed to establish async runtime")?;
111+
.into_diagnostic()
112+
.wrap_err("Failed to establish async runtime")?;
110113
let code = rt.block_on(self.run_async())?;
111114
// the monitor is running in the background and, although not expected,
112115
// can take extra time to shutdown if needed

crates/spfs-cli/cmd-render/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ path = "src/cmd_render.rs"
1212
sentry = ["spfs-cli-common/sentry"]
1313

1414
[dependencies]
15-
anyhow = { workspace = true }
1615
clap = { workspace = true }
1716
dunce = { workspace = true }
1817
futures = { workspace = true }
18+
miette = { workspace = true, features = ["fancy"] }
1919
serde_json = { workspace = true }
2020
spfs = { path = "../../spfs" }
2121
spfs-cli-common = { path = "../common" }

0 commit comments

Comments
 (0)