Split error mod and split generic/specific io errors
This commit is contained in:
parent
6a925fc392
commit
c821faf383
|
@ -1107,9 +1107,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "miette"
|
||||
version = "3.2.0"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec47e61dc212c43f44dcd1f2841ccba79c6ec10da357cab7a7859b5f87bd27a9"
|
||||
checksum = "cd2adcfcced5d625bf90a958a82ae5b93231f57f3df1383fee28c9b5096d35ed"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"backtrace",
|
||||
|
@ -1119,16 +1119,16 @@ dependencies = [
|
|||
"supports-color",
|
||||
"supports-hyperlinks",
|
||||
"supports-unicode",
|
||||
"term_size",
|
||||
"terminal_size",
|
||||
"textwrap 0.14.2",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miette-derive"
|
||||
version = "3.2.0"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c0f0b6f999b9a9f7e86322125583a437cf015054b7aaa9926dff0ff13005b7e"
|
||||
checksum = "5c01a8b61312d367ce87956bb686731f87e4c6dd5dbc550e8f06e3c24fb1f67f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1361,9 +1361,9 @@ checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
|||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "2.1.0"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a61765925aec40abdb23812a3a1a01fafc6ffb9da22768b2ce665a9e84e527c"
|
||||
checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
|
|
|
@ -9,7 +9,7 @@ pub fn init(_args: &ArgMatches<'static>) -> Result<InitConfig> {
|
|||
let mut config = InitConfig::default();
|
||||
config.on_error(SyncFnHandler::from(
|
||||
|data| -> std::result::Result<(), Infallible> {
|
||||
if let RuntimeError::IoError(_) = data {
|
||||
if let RuntimeError::IoErrorGeneric(_) = data {
|
||||
// these are often spurious, so condemn them to -v only
|
||||
error!("{}", data);
|
||||
return Ok(());
|
||||
|
|
293
lib/src/error.rs
293
lib/src/error.rs
|
@ -1,287 +1,12 @@
|
|||
//! Error types for critical, runtime, and specialised errors.
|
||||
|
||||
use std::path::PathBuf;
|
||||
#[doc(inline)]
|
||||
pub use critical::*;
|
||||
#[doc(inline)]
|
||||
pub use runtime::*;
|
||||
#[doc(inline)]
|
||||
pub use specialised::*;
|
||||
|
||||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
use tokio::{
|
||||
sync::{mpsc, watch},
|
||||
task::JoinError,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
action,
|
||||
event::Event,
|
||||
fs::{self, Watcher},
|
||||
signal::process::SubSignal,
|
||||
};
|
||||
|
||||
/// Errors which are not recoverable and stop watchexec execution.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[non_exhaustive]
|
||||
#[diagnostic(url(docsrs))]
|
||||
pub enum CriticalError {
|
||||
/// Pseudo-error used to signal a graceful exit.
|
||||
#[error("this should never be printed (exit)")]
|
||||
#[diagnostic(code(watchexec::runtime::exit))]
|
||||
Exit,
|
||||
|
||||
/// For custom critical errors.
|
||||
///
|
||||
/// This should be used for errors by external code which are not covered by the other error
|
||||
/// types; watchexec-internal errors should never use this.
|
||||
#[error("external(critical): {0}")]
|
||||
#[diagnostic(code(watchexec::critical::external))]
|
||||
External(#[from] Box<dyn std::error::Error + Send + Sync>),
|
||||
|
||||
/// A critical I/O error occurred.
|
||||
#[error(transparent)]
|
||||
#[diagnostic(code(watchexec::critical::io_error))]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
/// Error received when a runtime error cannot be sent to the errors channel.
|
||||
#[error("cannot send internal runtime error: {0}")]
|
||||
#[diagnostic(code(watchexec::critical::error_channel_send))]
|
||||
ErrorChannelSend(#[from] mpsc::error::SendError<RuntimeError>),
|
||||
|
||||
/// Error received when an event cannot be sent to the events channel.
|
||||
#[error("cannot send event to internal channel: {0}")]
|
||||
#[diagnostic(code(watchexec::critical::event_channel_send))]
|
||||
EventChannelSend(#[from] mpsc::error::SendError<Event>),
|
||||
|
||||
/// Error received when joining the main watchexec task.
|
||||
#[error("main task join: {0}")]
|
||||
#[diagnostic(code(watchexec::critical::main_task_join))]
|
||||
MainTaskJoin(#[source] JoinError),
|
||||
|
||||
/// Error received when a handler is missing on initialisation.
|
||||
///
|
||||
/// This is a **bug** and should be reported.
|
||||
#[error("internal: missing handler on init")]
|
||||
#[diagnostic(code(watchexec::critical::internal::missing_handler))]
|
||||
MissingHandler,
|
||||
}
|
||||
|
||||
/// Errors which _may_ be recoverable, transient, or only affect a part of the operation, and should
|
||||
/// be reported to the user and/or acted upon programatically, but will not outright stop watchexec.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[non_exhaustive]
|
||||
#[diagnostic(url(docsrs))]
|
||||
pub enum RuntimeError {
|
||||
/// Pseudo-error used to signal a graceful exit.
|
||||
#[error("this should never be printed (exit)")]
|
||||
#[diagnostic(code(watchexec::runtime::exit))]
|
||||
Exit,
|
||||
|
||||
/// For custom runtime errors.
|
||||
///
|
||||
/// This should be used for errors by external code which are not covered by the other error
|
||||
/// types; watchexec-internal errors should never use this.
|
||||
#[error("external(runtime): {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::external))]
|
||||
External(#[from] Box<dyn std::error::Error + Send + Sync>),
|
||||
|
||||
/// Generic I/O error, with no additional context.
|
||||
#[error(transparent)]
|
||||
#[diagnostic(code(watchexec::runtime::io_error))]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
/// Error received when creating a filesystem watcher fails.
|
||||
#[error("{kind:?} watcher failed to instantiate: {err}")]
|
||||
#[diagnostic(
|
||||
code(watchexec::runtime::fs_watcher_error),
|
||||
help("perhaps retry with the poll watcher")
|
||||
)]
|
||||
FsWatcherCreate {
|
||||
/// The kind of watcher that failed to instantiate.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Error received when reading a filesystem event fails.
|
||||
#[error("{kind:?} watcher received an event that we could not read: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::fs_watcher_event))]
|
||||
FsWatcherEvent {
|
||||
/// The kind of watcher that failed to read an event.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Error received when adding to the pathset for the filesystem watcher fails.
|
||||
#[error("while adding {path:?} to the {kind:?} watcher: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::fs_watcher_path_add))]
|
||||
FsWatcherPathAdd {
|
||||
/// The path that was attempted to be added.
|
||||
path: PathBuf,
|
||||
|
||||
/// The kind of watcher that failed to add a path.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Error received when removing from the pathset for the filesystem watcher fails.
|
||||
#[error("while removing {path:?} from the {kind:?} watcher: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::fs_watcher_path_remove))]
|
||||
FsWatcherPathRemove {
|
||||
/// The path that was attempted to be removed.
|
||||
path: PathBuf,
|
||||
|
||||
/// The kind of watcher that failed to remove a path.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Opaque internal error from a command supervisor.
|
||||
#[error("internal: command supervisor: {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::internal_supervisor))]
|
||||
InternalSupervisor(String),
|
||||
|
||||
/// Error received when an event cannot be sent to the event channel.
|
||||
#[error("cannot send event from {ctx}: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::event_channel_send))]
|
||||
EventChannelSend {
|
||||
/// The context in which this error happened.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
ctx: &'static str,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: mpsc::error::SendError<Event>,
|
||||
},
|
||||
|
||||
/// Error received when an event cannot be sent to the event channel.
|
||||
#[error("cannot send event from {ctx}: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::event_channel_try_send))]
|
||||
EventChannelTrySend {
|
||||
/// The context in which this error happened.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
ctx: &'static str,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: mpsc::error::TrySendError<Event>,
|
||||
},
|
||||
|
||||
/// Error received when a [`Handler`][crate::handler::Handler] errors.
|
||||
///
|
||||
/// The error is completely opaque, having been flattened into a string at the error point.
|
||||
#[error("handler error while {ctx}: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::handler))]
|
||||
Handler {
|
||||
/// The context in which this error happened.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
ctx: &'static str,
|
||||
|
||||
/// The underlying error, as the Display representation of the original error.
|
||||
err: String,
|
||||
},
|
||||
|
||||
/// Error received when a [`Handler`][crate::handler::Handler] which has been passed a lock has kept that lock open after the handler has completed.
|
||||
#[error("{0} handler returned while holding a lock alive")]
|
||||
#[diagnostic(code(watchexec::runtime::handler_lock_held))]
|
||||
HandlerLockHeld(&'static str),
|
||||
|
||||
/// Error received when operating on a process.
|
||||
#[error("when operating on process: {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::process))]
|
||||
Process(#[source] std::io::Error),
|
||||
|
||||
/// Error received when a process did not start correctly, or finished before we could even tell.
|
||||
#[error("process was dead on arrival")]
|
||||
#[diagnostic(code(watchexec::runtime::process_doa))]
|
||||
ProcessDeadOnArrival,
|
||||
|
||||
/// Error received when a [`SubSignal`] is unsupported
|
||||
///
|
||||
/// This may happen if the signal is not supported on the current platform, or if Watchexec
|
||||
/// doesn't support sending the signal.
|
||||
#[error("unsupported signal: {0:?}")]
|
||||
#[diagnostic(code(watchexec::runtime::unsupported_signal))]
|
||||
UnsupportedSignal(SubSignal),
|
||||
|
||||
/// Error received when clearing the screen.
|
||||
#[error("clear screen: {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::clearscreen))]
|
||||
Clearscreen(#[from] clearscreen::Error),
|
||||
|
||||
/// Error received when parsing a glob (possibly from an [`IgnoreFile`](crate::ignore::files::IgnoreFile)) fails.
|
||||
#[error("cannot parse glob from ignore '{file:?}': {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::ignore_glob))]
|
||||
GlobsetGlob {
|
||||
/// The path to the erroring ignore file.
|
||||
file: Option<PathBuf>,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: ignore::Error,
|
||||
// TODO: extract glob error into diagnostic
|
||||
},
|
||||
|
||||
/// Error received when an [`IgnoreFile`](crate::ignore::files::IgnoreFile) cannot be read.
|
||||
#[error("cannot read ignore '{file}': {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::ignore_file_read))]
|
||||
IgnoreFileRead {
|
||||
/// The path to the erroring ignore file.
|
||||
file: PathBuf,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: std::io::Error,
|
||||
},
|
||||
|
||||
/// Error emitted by a [`Filterer`](crate::filter::Filterer).
|
||||
///
|
||||
/// With built-in filterers this will probably be a dynbox of
|
||||
/// [`TaggedFiltererError`](crate::filter::tagged::error::TaggedFiltererError), but it is
|
||||
/// possible to use a custom filterer which emits a different error type.
|
||||
#[error("{kind} filterer: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::filterer))]
|
||||
Filterer {
|
||||
/// The kind of filterer that failed.
|
||||
///
|
||||
/// This should be set by the filterer itself to a short name for the filterer.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
kind: &'static str,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
|
||||
/// A set of related [`RuntimeError`]s.
|
||||
#[error("related: {0:?}")]
|
||||
#[diagnostic(code(watchexec::runtime::set))]
|
||||
Set(#[related] Vec<RuntimeError>),
|
||||
}
|
||||
|
||||
/// Errors occurring from reconfigs.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[non_exhaustive]
|
||||
#[diagnostic(url(docsrs))]
|
||||
pub enum ReconfigError {
|
||||
/// Error received when the action processor cannot be updated.
|
||||
#[error("reconfig: action watch: {0}")]
|
||||
#[diagnostic(code(watchexec::reconfig::action_watch))]
|
||||
ActionWatch(#[from] watch::error::SendError<action::WorkingData>),
|
||||
|
||||
/// Error received when the fs event source cannot be updated.
|
||||
#[error("reconfig: fs watch: {0}")]
|
||||
#[diagnostic(code(watchexec::reconfig::fs_watch))]
|
||||
FsWatch(#[from] watch::error::SendError<fs::WorkingData>),
|
||||
}
|
||||
mod critical;
|
||||
mod runtime;
|
||||
mod specialised;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
use tokio::{sync::mpsc, task::JoinError};
|
||||
|
||||
use crate::event::Event;
|
||||
|
||||
use super::RuntimeError;
|
||||
|
||||
/// Errors which are not recoverable and stop watchexec execution.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[non_exhaustive]
|
||||
#[diagnostic(url(docsrs))]
|
||||
pub enum CriticalError {
|
||||
/// Pseudo-error used to signal a graceful exit.
|
||||
#[error("this should never be printed (exit)")]
|
||||
#[diagnostic(code(watchexec::runtime::exit))]
|
||||
Exit,
|
||||
|
||||
/// For custom critical errors.
|
||||
///
|
||||
/// This should be used for errors by external code which are not covered by the other error
|
||||
/// types; watchexec-internal errors should never use this.
|
||||
#[error("external(critical): {0}")]
|
||||
#[diagnostic(code(watchexec::critical::external))]
|
||||
External(#[from] Box<dyn std::error::Error + Send + Sync>),
|
||||
|
||||
/// A critical I/O error occurred (generic).
|
||||
#[error("io(unspecified): {0}")]
|
||||
#[diagnostic(code(watchexec::critical::io_error_generic))]
|
||||
IoErrorGeneric(#[from] std::io::Error),
|
||||
|
||||
/// A critical I/O error occurred (specific).
|
||||
#[error("io({about}): {err}")]
|
||||
#[diagnostic(code(watchexec::critical::io_error))]
|
||||
IoError {
|
||||
/// What it was about.
|
||||
about: &'static str,
|
||||
|
||||
/// The I/O error which occurred.
|
||||
#[source]
|
||||
err: std::io::Error,
|
||||
},
|
||||
|
||||
/// Error received when a runtime error cannot be sent to the errors channel.
|
||||
#[error("cannot send internal runtime error: {0}")]
|
||||
#[diagnostic(code(watchexec::critical::error_channel_send))]
|
||||
ErrorChannelSend(#[from] mpsc::error::SendError<RuntimeError>),
|
||||
|
||||
/// Error received when an event cannot be sent to the events channel.
|
||||
#[error("cannot send event to internal channel: {0}")]
|
||||
#[diagnostic(code(watchexec::critical::event_channel_send))]
|
||||
EventChannelSend(#[from] mpsc::error::SendError<Event>),
|
||||
|
||||
/// Error received when joining the main watchexec task.
|
||||
#[error("main task join: {0}")]
|
||||
#[diagnostic(code(watchexec::critical::main_task_join))]
|
||||
MainTaskJoin(#[source] JoinError),
|
||||
|
||||
/// Error received when a handler is missing on initialisation.
|
||||
///
|
||||
/// This is a **bug** and should be reported.
|
||||
#[error("internal: missing handler on init")]
|
||||
#[diagnostic(code(watchexec::critical::internal::missing_handler))]
|
||||
MissingHandler,
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::{event::Event, fs::Watcher, signal::process::SubSignal};
|
||||
|
||||
/// Errors which _may_ be recoverable, transient, or only affect a part of the operation, and should
|
||||
/// be reported to the user and/or acted upon programatically, but will not outright stop watchexec.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[non_exhaustive]
|
||||
#[diagnostic(url(docsrs))]
|
||||
pub enum RuntimeError {
|
||||
/// Pseudo-error used to signal a graceful exit.
|
||||
#[error("this should never be printed (exit)")]
|
||||
#[diagnostic(code(watchexec::runtime::exit))]
|
||||
Exit,
|
||||
|
||||
/// For custom runtime errors.
|
||||
///
|
||||
/// This should be used for errors by external code which are not covered by the other error
|
||||
/// types; watchexec-internal errors should never use this.
|
||||
#[error("external(runtime): {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::external))]
|
||||
External(#[from] Box<dyn std::error::Error + Send + Sync>),
|
||||
|
||||
/// Generic I/O error, with no additional context.
|
||||
#[error("io(unspecified): {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::io_error_generic))]
|
||||
IoErrorGeneric(#[from] std::io::Error),
|
||||
|
||||
/// Generic I/O error, with some context.
|
||||
#[error("io({about}): {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::io_error))]
|
||||
IoError {
|
||||
/// What it was about.
|
||||
about: &'static str,
|
||||
|
||||
/// The I/O error which occurred.
|
||||
#[source]
|
||||
err: std::io::Error,
|
||||
},
|
||||
|
||||
/// Error received when creating a filesystem watcher fails.
|
||||
#[error("{kind:?} watcher failed to instantiate: {err}")]
|
||||
#[diagnostic(
|
||||
code(watchexec::runtime::fs_watcher_error),
|
||||
help("perhaps retry with the poll watcher")
|
||||
)]
|
||||
FsWatcherCreate {
|
||||
/// The kind of watcher that failed to instantiate.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Error received when reading a filesystem event fails.
|
||||
#[error("{kind:?} watcher received an event that we could not read: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::fs_watcher_event))]
|
||||
FsWatcherEvent {
|
||||
/// The kind of watcher that failed to read an event.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Error received when adding to the pathset for the filesystem watcher fails.
|
||||
#[error("while adding {path:?} to the {kind:?} watcher: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::fs_watcher_path_add))]
|
||||
FsWatcherPathAdd {
|
||||
/// The path that was attempted to be added.
|
||||
path: PathBuf,
|
||||
|
||||
/// The kind of watcher that failed to add a path.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Error received when removing from the pathset for the filesystem watcher fails.
|
||||
#[error("while removing {path:?} from the {kind:?} watcher: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::fs_watcher_path_remove))]
|
||||
FsWatcherPathRemove {
|
||||
/// The path that was attempted to be removed.
|
||||
path: PathBuf,
|
||||
|
||||
/// The kind of watcher that failed to remove a path.
|
||||
kind: Watcher,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: notify::Error,
|
||||
},
|
||||
|
||||
/// Opaque internal error from a command supervisor.
|
||||
#[error("internal: command supervisor: {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::internal_supervisor))]
|
||||
InternalSupervisor(String),
|
||||
|
||||
/// Error received when an event cannot be sent to the event channel.
|
||||
#[error("cannot send event from {ctx}: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::event_channel_send))]
|
||||
EventChannelSend {
|
||||
/// The context in which this error happened.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
ctx: &'static str,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: mpsc::error::SendError<Event>,
|
||||
},
|
||||
|
||||
/// Error received when an event cannot be sent to the event channel.
|
||||
#[error("cannot send event from {ctx}: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::event_channel_try_send))]
|
||||
EventChannelTrySend {
|
||||
/// The context in which this error happened.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
ctx: &'static str,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: mpsc::error::TrySendError<Event>,
|
||||
},
|
||||
|
||||
/// Error received when a [`Handler`][crate::handler::Handler] errors.
|
||||
///
|
||||
/// The error is completely opaque, having been flattened into a string at the error point.
|
||||
#[error("handler error while {ctx}: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::handler))]
|
||||
Handler {
|
||||
/// The context in which this error happened.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
ctx: &'static str,
|
||||
|
||||
/// The underlying error, as the Display representation of the original error.
|
||||
err: String,
|
||||
},
|
||||
|
||||
/// Error received when a [`Handler`][crate::handler::Handler] which has been passed a lock has kept that lock open after the handler has completed.
|
||||
#[error("{0} handler returned while holding a lock alive")]
|
||||
#[diagnostic(code(watchexec::runtime::handler_lock_held))]
|
||||
HandlerLockHeld(&'static str),
|
||||
|
||||
/// Error received when operating on a process.
|
||||
#[error("when operating on process: {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::process))]
|
||||
Process(#[source] std::io::Error),
|
||||
|
||||
/// Error received when a process did not start correctly, or finished before we could even tell.
|
||||
#[error("process was dead on arrival")]
|
||||
#[diagnostic(code(watchexec::runtime::process_doa))]
|
||||
ProcessDeadOnArrival,
|
||||
|
||||
/// Error received when a [`SubSignal`] is unsupported
|
||||
///
|
||||
/// This may happen if the signal is not supported on the current platform, or if Watchexec
|
||||
/// doesn't support sending the signal.
|
||||
#[error("unsupported signal: {0:?}")]
|
||||
#[diagnostic(code(watchexec::runtime::unsupported_signal))]
|
||||
UnsupportedSignal(SubSignal),
|
||||
|
||||
/// Error received when clearing the screen.
|
||||
#[error("clear screen: {0}")]
|
||||
#[diagnostic(code(watchexec::runtime::clearscreen))]
|
||||
Clearscreen(#[from] clearscreen::Error),
|
||||
|
||||
/// Error received when parsing a glob (possibly from an [`IgnoreFile`](crate::ignore::files::IgnoreFile)) fails.
|
||||
#[error("cannot parse glob from ignore '{file:?}': {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::ignore_glob))]
|
||||
GlobsetGlob {
|
||||
/// The path to the erroring ignore file.
|
||||
file: Option<PathBuf>,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: ignore::Error,
|
||||
// TODO: extract glob error into diagnostic
|
||||
},
|
||||
|
||||
/// Error received when an [`IgnoreFile`](crate::ignore::files::IgnoreFile) cannot be read.
|
||||
#[error("cannot read ignore '{file}': {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::ignore_file_read))]
|
||||
IgnoreFileRead {
|
||||
/// The path to the erroring ignore file.
|
||||
file: PathBuf,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: std::io::Error,
|
||||
},
|
||||
|
||||
/// Error emitted by a [`Filterer`](crate::filter::Filterer).
|
||||
///
|
||||
/// With built-in filterers this will probably be a dynbox of
|
||||
/// [`TaggedFiltererError`](crate::filter::tagged::error::TaggedFiltererError), but it is
|
||||
/// possible to use a custom filterer which emits a different error type.
|
||||
#[error("{kind} filterer: {err}")]
|
||||
#[diagnostic(code(watchexec::runtime::filterer))]
|
||||
Filterer {
|
||||
/// The kind of filterer that failed.
|
||||
///
|
||||
/// This should be set by the filterer itself to a short name for the filterer.
|
||||
///
|
||||
/// This is not stable and its value should not be relied on except for printing the error.
|
||||
kind: &'static str,
|
||||
|
||||
/// The underlying error.
|
||||
#[source]
|
||||
err: Box<dyn std::error::Error + Send + Sync>,
|
||||
},
|
||||
|
||||
/// A set of related [`RuntimeError`]s.
|
||||
#[error("related: {0:?}")]
|
||||
#[diagnostic(code(watchexec::runtime::set))]
|
||||
Set(#[related] Vec<RuntimeError>),
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::watch;
|
||||
|
||||
use crate::{action, fs};
|
||||
|
||||
/// Errors occurring from reconfigs.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[non_exhaustive]
|
||||
#[diagnostic(url(docsrs))]
|
||||
pub enum ReconfigError {
|
||||
/// Error received when the action processor cannot be updated.
|
||||
#[error("reconfig: action watch: {0}")]
|
||||
#[diagnostic(code(watchexec::reconfig::action_watch))]
|
||||
ActionWatch(#[from] watch::error::SendError<action::WorkingData>),
|
||||
|
||||
/// Error received when the fs event source cannot be updated.
|
||||
#[error("reconfig: fs watch: {0}")]
|
||||
#[diagnostic(code(watchexec::reconfig::fs_watch))]
|
||||
FsWatch(#[from] watch::error::SendError<fs::WorkingData>),
|
||||
}
|
||||
|
||||
/// Error when parsing a glob pattern from string.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[error("invalid glob `{src}`: {err}")]
|
||||
#[diagnostic(code(watchexec::filter::glob_parse), url(docsrs))]
|
||||
pub struct GlobParseError {
|
||||
// The string that was parsed.
|
||||
#[source_code]
|
||||
src: String,
|
||||
|
||||
// The error that occurred.
|
||||
err: String,
|
||||
|
||||
// The span of the source which is in error.
|
||||
#[label = "invalid"]
|
||||
span: (usize, usize),
|
||||
}
|
||||
|
||||
impl GlobParseError {
|
||||
pub(crate) fn new(src: &str, err: &str) -> Self {
|
||||
Self {
|
||||
src: src.to_owned(),
|
||||
err: err.to_owned(),
|
||||
span: (0, src.len()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error when parsing a signal from string.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[error("invalid signal `{src}`: {err}")]
|
||||
#[diagnostic(code(watchexec::signal::process::parse), url(docsrs))]
|
||||
pub struct SignalParseError {
|
||||
// The string that was parsed.
|
||||
#[source_code]
|
||||
src: String,
|
||||
|
||||
// The error that occurred.
|
||||
err: String,
|
||||
|
||||
// The span of the source which is in error.
|
||||
#[label = "invalid signal"]
|
||||
span: (usize, usize),
|
||||
}
|
||||
|
||||
impl SignalParseError {
|
||||
pub(crate) fn new(src: &str, err: &str) -> Self {
|
||||
Self {
|
||||
src: src.to_owned(),
|
||||
err: err.to_owned(),
|
||||
span: (0, src.len()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,10 +3,11 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ignore::gitignore::GitignoreBuilder;
|
||||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{error::RuntimeError, event::Event};
|
||||
use crate::{
|
||||
error::{GlobParseError, RuntimeError},
|
||||
event::Event,
|
||||
};
|
||||
|
||||
pub mod globset;
|
||||
pub mod tagged;
|
||||
|
@ -54,30 +55,3 @@ pub fn check_glob(glob: &str) -> Result<(), GlobParseError> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Error when parsing a glob pattern from string.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[error("invalid glob `{src}`: {err}")]
|
||||
#[diagnostic(code(watchexec::filter::glob_parse), url(docsrs))]
|
||||
pub struct GlobParseError {
|
||||
// The string that was parsed.
|
||||
#[source_code]
|
||||
src: String,
|
||||
|
||||
// The error that occurred.
|
||||
err: String,
|
||||
|
||||
// The span of the source which is in error.
|
||||
#[label = "invalid"]
|
||||
span: (usize, usize),
|
||||
}
|
||||
|
||||
impl GlobParseError {
|
||||
fn new(src: &str, err: &str) -> Self {
|
||||
Self {
|
||||
src: src.to_owned(),
|
||||
err: err.to_owned(),
|
||||
span: (0, src.len()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ use std::str::FromStr;
|
|||
|
||||
#[cfg(unix)]
|
||||
use command_group::Signal as NixSignal;
|
||||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::error::SignalParseError;
|
||||
|
||||
use super::source::MainSignal;
|
||||
|
||||
|
@ -210,30 +210,3 @@ impl FromStr for SubSignal {
|
|||
Err(SignalParseError::new(s, "no signals supported"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Error when parsing a signal from string.
|
||||
#[derive(Debug, Diagnostic, Error)]
|
||||
#[error("invalid signal `{src}`: {err}")]
|
||||
#[diagnostic(code(watchexec::signal::process::parse), url(docsrs))]
|
||||
pub struct SignalParseError {
|
||||
// The string that was parsed.
|
||||
#[source_code]
|
||||
src: String,
|
||||
|
||||
// The error that occurred.
|
||||
err: String,
|
||||
|
||||
// The span of the source which is in error.
|
||||
#[label = "invalid signal"]
|
||||
span: (usize, usize),
|
||||
}
|
||||
|
||||
impl SignalParseError {
|
||||
fn new(src: &str, err: &str) -> Self {
|
||||
Self {
|
||||
src: src.to_owned(),
|
||||
err: err.to_owned(),
|
||||
span: (0, src.len()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue