watchexec/lib/src/error.rs

288 lines
9.5 KiB
Rust
Raw Normal View History

//! Error types for critical, runtime, and specialised errors.
use std::path::PathBuf;
2021-08-16 11:49:12 +02:00
use miette::Diagnostic;
2021-08-16 15:15:17 +02:00
use thiserror::Error;
2021-08-18 15:12:50 +02:00
use tokio::{
sync::{mpsc, watch},
task::JoinError,
};
use crate::{
action,
event::Event,
fs::{self, Watcher},
2021-10-16 15:24:36 +02:00
signal::process::SubSignal,
};
2021-08-16 11:49:12 +02:00
/// Errors which are not recoverable and stop watchexec execution.
#[derive(Debug, Diagnostic, Error)]
#[non_exhaustive]
#[diagnostic(url(docsrs))]
2021-08-16 11:49:12 +02:00
pub enum CriticalError {
2021-08-22 16:32:08 +02:00
/// 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>),
2021-08-16 11:49:12 +02:00
/// 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.
2021-08-16 11:49:12 +02:00
#[error("cannot send internal runtime error: {0}")]
#[diagnostic(code(watchexec::critical::error_channel_send))]
ErrorChannelSend(#[from] mpsc::error::SendError<RuntimeError>),
2021-08-18 15:12:50 +02:00
/// 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>),
2021-08-18 15:12:50 +02:00
/// Error received when joining the main watchexec task.
#[error("main task join: {0}")]
#[diagnostic(code(watchexec::critical::main_task_join))]
MainTaskJoin(#[source] JoinError),
2021-08-21 19:58:03 +02:00
/// Error received when a handler is missing on initialisation.
///
2021-08-22 16:32:08 +02:00
/// This is a **bug** and should be reported.
2021-08-21 19:58:03 +02:00
#[error("internal: missing handler on init")]
#[diagnostic(code(watchexec::critical::internal::missing_handler))]
MissingHandler,
}
2021-08-16 11:49:12 +02:00
/// 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))]
2021-08-16 11:49:12 +02:00
pub enum RuntimeError {
2021-08-22 16:32:08 +02:00
/// 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>),
2021-08-16 11:49:12 +02:00
/// Generic I/O error, with no additional context.
#[error(transparent)]
#[diagnostic(code(watchexec::runtime::io_error))]
IoError(#[from] std::io::Error),
2021-08-16 11:49:12 +02:00
/// Error received when creating a filesystem watcher fails.
#[error("{kind:?} watcher failed to instantiate: {err}")]
#[diagnostic(
code(watchexec::runtime::fs_watcher_error),
2021-08-16 15:15:17 +02:00
help("perhaps retry with the poll watcher")
2021-08-16 11:49:12 +02:00
)]
2021-08-16 15:15:17 +02:00
FsWatcherCreate {
2021-10-16 15:32:43 +02:00
/// The kind of watcher that failed to instantiate.
2021-08-16 15:15:17 +02:00
kind: Watcher,
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-08-16 15:15:17 +02:00
#[source]
err: notify::Error,
},
2021-08-16 11:49:12 +02:00
/// Error received when reading a filesystem event fails.
#[error("{kind:?} watcher received an event that we could not read: {err}")]
2021-08-16 15:15:17 +02:00
#[diagnostic(code(watchexec::runtime::fs_watcher_event))]
FsWatcherEvent {
2021-10-16 15:32:43 +02:00
/// The kind of watcher that failed to read an event.
2021-08-16 15:15:17 +02:00
kind: Watcher,
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-08-16 15:15:17 +02:00
#[source]
err: notify::Error,
},
2021-08-16 11:49:12 +02:00
/// Error received when adding to the pathset for the filesystem watcher fails.
#[error("while adding {path:?} to the {kind:?} watcher: {err}")]
2021-08-16 15:15:17 +02:00
#[diagnostic(code(watchexec::runtime::fs_watcher_path_add))]
FsWatcherPathAdd {
2021-10-16 15:32:43 +02:00
/// The path that was attempted to be added.
2021-08-16 15:15:17 +02:00
path: PathBuf,
2021-10-16 15:32:43 +02:00
/// The kind of watcher that failed to add a path.
2021-08-16 15:15:17 +02:00
kind: Watcher,
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-08-16 15:15:17 +02:00
#[source]
err: notify::Error,
},
2021-08-16 11:49:12 +02:00
/// Error received when removing from the pathset for the filesystem watcher fails.
#[error("while removing {path:?} from the {kind:?} watcher: {err}")]
2021-08-16 15:15:17 +02:00
#[diagnostic(code(watchexec::runtime::fs_watcher_path_remove))]
FsWatcherPathRemove {
2021-10-16 15:32:43 +02:00
/// The path that was attempted to be removed.
2021-08-16 15:15:17 +02:00
path: PathBuf,
2021-10-16 15:32:43 +02:00
/// The kind of watcher that failed to remove a path.
2021-08-16 15:15:17 +02:00
kind: Watcher,
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-08-16 15:15:17 +02:00
#[source]
err: notify::Error,
},
/// Opaque internal error from a command supervisor.
#[error("internal: command supervisor: {0}")]
#[diagnostic(code(watchexec::runtime::internal_supervisor))]
InternalSupervisor(String),
2021-08-16 11:49:12 +02:00
/// 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))]
2021-08-16 15:15:17 +02:00
EventChannelSend {
2021-10-16 15:32:43 +02:00
/// The context in which this error happened.
///
/// This is not stable and its value should not be relied on except for printing the error.
2021-08-17 11:41:13 +02:00
ctx: &'static str,
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-08-17 11:41:13 +02:00
#[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 {
2021-10-16 15:32:43 +02:00
/// The context in which this error happened.
///
/// This is not stable and its value should not be relied on except for printing the error.
2021-08-16 15:15:17 +02:00
ctx: &'static str,
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-08-16 15:15:17 +02:00
#[source]
err: mpsc::error::TrySendError<Event>,
},
2021-08-19 10:30:35 +02:00
/// Error received when a [`Handler`][crate::handler::Handler] errors.
2021-08-19 10:30:35 +02:00
///
/// 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))]
2021-10-16 15:32:43 +02:00
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,
},
2021-08-22 14:28:20 +02:00
2021-08-24 18:41:14 +02:00
/// 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),
2021-08-22 14:28:20 +02:00
/// Error received when operating on a process.
#[error("when operating on process: {0}")]
#[diagnostic(code(watchexec::runtime::process))]
Process(#[source] std::io::Error),
2021-08-24 18:41:14 +02:00
/// 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,
2021-10-16 15:24:36 +02:00
/// 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),
2021-08-22 14:28:20 +02:00
/// Error received when clearing the screen.
#[error("clear screen: {0}")]
#[diagnostic(code(watchexec::runtime::clearscreen))]
Clearscreen(#[from] clearscreen::Error),
2021-09-14 10:09:57 +02:00
/// 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).
///
2021-10-16 15:32:43 +02:00
/// With built-in filterers this will probably be a dynbox of
2021-10-16 16:06:08 +02:00
/// [`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 {
2021-10-16 15:32:43 +02:00
/// 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,
2021-09-28 11:23:23 +02:00
2021-10-16 15:32:43 +02:00
/// The underlying error.
2021-09-28 11:23:23 +02:00
#[source]
err: Box<dyn std::error::Error + Send + Sync>,
2021-09-28 11:23:23 +02:00
},
/// A set of related [`RuntimeError`]s.
#[error("related: {0:?}")]
#[diagnostic(code(watchexec::runtime::set))]
Set(#[related] Vec<RuntimeError>),
2021-08-19 10:30:35 +02:00
}
2021-08-18 15:12:50 +02:00
/// Errors occurring from reconfigs.
#[derive(Debug, Diagnostic, Error)]
#[non_exhaustive]
#[diagnostic(url(docsrs))]
2021-08-18 15:12:50 +02:00
pub enum ReconfigError {
2021-08-20 18:43:55 +02:00
/// 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.
2021-08-18 15:12:50 +02:00
#[error("reconfig: fs watch: {0}")]
#[diagnostic(code(watchexec::reconfig::fs_watch))]
FsWatch(#[from] watch::error::SendError<fs::WorkingData>),
}