mirror of
https://github.com/nushell/nushell.git
synced 2025-08-14 03:38:33 +02:00
Move job errors into ShellError::Job
variant (#15820)
- related #10698 # Description In my endeavor to make the `ShellError` less crowded I moved the job related errors into `ShellError::Job` with a `JobError` enum. Mostly I just moved the codes, errors and labels over to the new enum.
This commit is contained in:
@ -34,21 +34,13 @@ impl Command for JobKill {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
|
|
||||||
let id_arg: Spanned<i64> = call.req(engine_state, stack, 0)?;
|
let id_arg: Spanned<usize> = call.req(engine_state, stack, 0)?;
|
||||||
|
let id = JobId::new(id_arg.item);
|
||||||
if id_arg.item < 0 {
|
|
||||||
return Err(ShellError::NeedsPositiveValue { span: id_arg.span });
|
|
||||||
}
|
|
||||||
|
|
||||||
let id: JobId = JobId::new(id_arg.item as usize);
|
|
||||||
|
|
||||||
let mut jobs = engine_state.jobs.lock().expect("jobs lock is poisoned!");
|
let mut jobs = engine_state.jobs.lock().expect("jobs lock is poisoned!");
|
||||||
|
|
||||||
if jobs.lookup(id).is_none() {
|
if jobs.lookup(id).is_none() {
|
||||||
return Err(ShellError::JobNotFound {
|
return Err(JobError::NotFound { span: head, id }.into());
|
||||||
id: id.get(),
|
|
||||||
span: head,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs.kill_and_remove(id).map_err(|err| {
|
jobs.kill_and_remove(id).map_err(|err| {
|
||||||
|
@ -145,7 +145,7 @@ fn recv_instantly(
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
match mailbox.try_recv(tag) {
|
match mailbox.try_recv(tag) {
|
||||||
Ok(value) => Ok(value),
|
Ok(value) => Ok(value),
|
||||||
Err(TryRecvError::Empty) => Err(ShellError::RecvTimeout { span }),
|
Err(TryRecvError::Empty) => Err(JobError::RecvTimeout { span }.into()),
|
||||||
Err(TryRecvError::Disconnected) => Err(ShellError::Interrupted { span }),
|
Err(TryRecvError::Disconnected) => Err(ShellError::Interrupted { span }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ fn recv_with_time_limit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if time_until_deadline.is_zero() {
|
if time_until_deadline.is_zero() {
|
||||||
return Err(ShellError::RecvTimeout { span });
|
return Err(JobError::RecvTimeout { span }.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,14 +52,10 @@ This command never blocks.
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
|
|
||||||
let id_arg: Spanned<i64> = call.req(engine_state, stack, 0)?;
|
let id_arg: Spanned<usize> = call.req(engine_state, stack, 0)?;
|
||||||
let tag_arg: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "tag")?;
|
let tag_arg: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "tag")?;
|
||||||
|
|
||||||
let id = id_arg.item;
|
let id = JobId::new(id_arg.item);
|
||||||
|
|
||||||
if id < 0 {
|
|
||||||
return Err(ShellError::NeedsPositiveValue { span: id_arg.span });
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tag) = tag_arg {
|
if let Some(tag) = tag_arg {
|
||||||
if tag.item < 0 {
|
if tag.item < 0 {
|
||||||
@ -69,7 +65,7 @@ This command never blocks.
|
|||||||
|
|
||||||
let tag = tag_arg.map(|it| it.item as FilterTag);
|
let tag = tag_arg.map(|it| it.item as FilterTag);
|
||||||
|
|
||||||
if id == 0 {
|
if id == JobId::ZERO {
|
||||||
engine_state
|
engine_state
|
||||||
.root_job_sender
|
.root_job_sender
|
||||||
.send((tag, input))
|
.send((tag, input))
|
||||||
@ -77,7 +73,7 @@ This command never blocks.
|
|||||||
} else {
|
} else {
|
||||||
let jobs = engine_state.jobs.lock().expect("failed to acquire lock");
|
let jobs = engine_state.jobs.lock().expect("failed to acquire lock");
|
||||||
|
|
||||||
if let Some(job) = jobs.lookup(JobId::new(id as usize)) {
|
if let Some(job) = jobs.lookup(id) {
|
||||||
match job {
|
match job {
|
||||||
nu_protocol::engine::Job::Thread(thread_job) => {
|
nu_protocol::engine::Job::Thread(thread_job) => {
|
||||||
// it is ok to send this value while holding the lock, because
|
// it is ok to send this value while holding the lock, because
|
||||||
@ -85,17 +81,19 @@ This command never blocks.
|
|||||||
let _ = thread_job.sender.send((tag, input));
|
let _ = thread_job.sender.send((tag, input));
|
||||||
}
|
}
|
||||||
nu_protocol::engine::Job::Frozen(_) => {
|
nu_protocol::engine::Job::Frozen(_) => {
|
||||||
return Err(ShellError::JobIsFrozen {
|
return Err(JobError::AlreadyFrozen {
|
||||||
id: id as usize,
|
|
||||||
span: id_arg.span,
|
span: id_arg.span,
|
||||||
});
|
id,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::JobNotFound {
|
return Err(JobError::NotFound {
|
||||||
id: id as usize,
|
|
||||||
span: id_arg.span,
|
span: id_arg.span,
|
||||||
});
|
id,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,26 +38,15 @@ impl Command for JobTag {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
|
|
||||||
let id_arg: Spanned<i64> = call.req(engine_state, stack, 0)?;
|
let id_arg: Spanned<usize> = call.req(engine_state, stack, 0)?;
|
||||||
|
let id = JobId::new(id_arg.item);
|
||||||
if id_arg.item < 0 {
|
|
||||||
return Err(ShellError::NeedsPositiveValue { span: id_arg.span });
|
|
||||||
}
|
|
||||||
|
|
||||||
let id: JobId = JobId::new(id_arg.item as usize);
|
|
||||||
|
|
||||||
let tag: Option<String> = call.req(engine_state, stack, 1)?;
|
let tag: Option<String> = call.req(engine_state, stack, 1)?;
|
||||||
|
|
||||||
let mut jobs = engine_state.jobs.lock().expect("jobs lock is poisoned!");
|
let mut jobs = engine_state.jobs.lock().expect("jobs lock is poisoned!");
|
||||||
|
|
||||||
match jobs.lookup_mut(id) {
|
match jobs.lookup_mut(id) {
|
||||||
None => {
|
None => return Err(JobError::NotFound { span: head, id }.into()),
|
||||||
return Err(ShellError::JobNotFound {
|
|
||||||
id: id.get(),
|
|
||||||
span: head,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(job) => job.assign_tag(tag),
|
Some(job) => job.assign_tag(tag),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,33 +39,18 @@ impl Command for JobUnfreeze {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
|
|
||||||
let option_id: Option<Spanned<i64>> = call.opt(engine_state, stack, 0)?;
|
|
||||||
|
|
||||||
let mut jobs = engine_state.jobs.lock().expect("jobs lock is poisoned!");
|
let mut jobs = engine_state.jobs.lock().expect("jobs lock is poisoned!");
|
||||||
|
|
||||||
if let Some(id_arg) = option_id {
|
let id: Option<usize> = call.opt(engine_state, stack, 0)?;
|
||||||
if id_arg.item < 0 {
|
let id = id
|
||||||
return Err(ShellError::NeedsPositiveValue { span: id_arg.span });
|
.map(JobId::new)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let id = option_id
|
|
||||||
.map(|it| JobId::new(it.item as usize))
|
|
||||||
.or_else(|| jobs.most_recent_frozen_job_id())
|
.or_else(|| jobs.most_recent_frozen_job_id())
|
||||||
.ok_or_else(|| ShellError::NoFrozenJob { span: head })?;
|
.ok_or(JobError::NoneToUnfreeze { span: head })?;
|
||||||
|
|
||||||
let job = match jobs.lookup(id) {
|
let job = match jobs.lookup(id) {
|
||||||
None => {
|
None => return Err(JobError::NotFound { span: head, id }.into()),
|
||||||
return Err(ShellError::JobNotFound {
|
|
||||||
id: id.get(),
|
|
||||||
span: head,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Some(Job::Thread(ThreadJob { .. })) => {
|
Some(Job::Thread(ThreadJob { .. })) => {
|
||||||
return Err(ShellError::JobNotFrozen {
|
return Err(JobError::CannotUnfreeze { span: head, id }.into());
|
||||||
id: id.get(),
|
|
||||||
span: head,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Some(Job::Frozen(FrozenJob { .. })) => jobs
|
Some(Job::Frozen(FrozenJob { .. })) => jobs
|
||||||
.remove_job(id)
|
.remove_job(id)
|
||||||
@ -107,11 +92,7 @@ fn unfreeze_job(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
match job {
|
match job {
|
||||||
Job::Thread(ThreadJob { .. }) => Err(ShellError::JobNotFrozen {
|
Job::Thread(ThreadJob { .. }) => Err(JobError::CannotUnfreeze { span, id: old_id }.into()),
|
||||||
id: old_id.get(),
|
|
||||||
span,
|
|
||||||
}),
|
|
||||||
|
|
||||||
Job::Frozen(FrozenJob {
|
Job::Frozen(FrozenJob {
|
||||||
unfreeze: handle,
|
unfreeze: handle,
|
||||||
tag,
|
tag,
|
||||||
|
@ -6,5 +6,5 @@ pub use nu_protocol::{
|
|||||||
ast::CellPath,
|
ast::CellPath,
|
||||||
engine::{Call, Command, EngineState, Stack, StateWorkingSet},
|
engine::{Call, Command, EngineState, Stack, StateWorkingSet},
|
||||||
record,
|
record,
|
||||||
shell_error::io::*,
|
shell_error::{io::*, job::*},
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ use thiserror::Error;
|
|||||||
|
|
||||||
use crate::Span;
|
use crate::Span;
|
||||||
|
|
||||||
use super::{ShellError, location::Location};
|
use super::location::Location;
|
||||||
|
|
||||||
/// Represents an I/O error in the [`ShellError::Io`] variant.
|
/// Represents an I/O error in the [`ShellError::Io`] variant.
|
||||||
///
|
///
|
||||||
@ -494,12 +494,6 @@ impl Diagnostic for IoError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IoError> for ShellError {
|
|
||||||
fn from(value: IoError) -> Self {
|
|
||||||
ShellError::Io(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<IoError> for std::io::Error {
|
impl From<IoError> for std::io::Error {
|
||||||
fn from(value: IoError) -> Self {
|
fn from(value: IoError) -> Self {
|
||||||
Self::new(value.kind.into(), value)
|
Self::new(value.kind.into(), value)
|
||||||
|
45
crates/nu-protocol/src/errors/shell_error/job.rs
Normal file
45
crates/nu-protocol/src/errors/shell_error/job.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use miette::Diagnostic;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::{JobId, Span};
|
||||||
|
|
||||||
|
/// Errors when working working with jobs.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Error, Diagnostic)]
|
||||||
|
pub enum JobError {
|
||||||
|
#[error("Job {id} not found")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::shell::job::not_found),
|
||||||
|
help(
|
||||||
|
"The operation could not be completed, there is no job currently running with this id"
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
NotFound { span: Span, id: JobId },
|
||||||
|
|
||||||
|
#[error("No frozen job to unfreeze")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::shell::job::none_to_unfreeze),
|
||||||
|
help("There is currently no frozen job to unfreeze")
|
||||||
|
)]
|
||||||
|
NoneToUnfreeze { span: Span },
|
||||||
|
|
||||||
|
#[error("Job {id} is not frozen")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::shell::job::cannot_unfreeze),
|
||||||
|
help("You tried to unfreeze a job which is not frozen")
|
||||||
|
)]
|
||||||
|
CannotUnfreeze { span: Span, id: JobId },
|
||||||
|
|
||||||
|
#[error("The job {id} is frozen")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::shell::job::already_frozen),
|
||||||
|
help("This operation cannot be performed because the job is frozen")
|
||||||
|
)]
|
||||||
|
AlreadyFrozen { span: Span, id: JobId },
|
||||||
|
|
||||||
|
#[error("No message was received in the requested time interval")]
|
||||||
|
#[diagnostic(
|
||||||
|
code(nu::shell::job::recv_timeout),
|
||||||
|
help("No message arrived within the specified time limit")
|
||||||
|
)]
|
||||||
|
RecvTimeout { span: Span },
|
||||||
|
}
|
@ -3,6 +3,7 @@ use crate::{
|
|||||||
ConfigError, LabeledError, ParseError, Span, Spanned, Type, Value, ast::Operator,
|
ConfigError, LabeledError, ParseError, Span, Spanned, Type, Value, ast::Operator,
|
||||||
engine::StateWorkingSet, format_shell_error, record,
|
engine::StateWorkingSet, format_shell_error, record,
|
||||||
};
|
};
|
||||||
|
use job::JobError;
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::num::NonZeroI32;
|
use std::num::NonZeroI32;
|
||||||
@ -10,6 +11,7 @@ use thiserror::Error;
|
|||||||
|
|
||||||
pub mod bridge;
|
pub mod bridge;
|
||||||
pub mod io;
|
pub mod io;
|
||||||
|
pub mod job;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
|
|
||||||
/// The fundamental error type for the evaluation engine. These cases represent different kinds of errors
|
/// The fundamental error type for the evaluation engine. These cases represent different kinds of errors
|
||||||
@ -917,7 +919,7 @@ pub enum ShellError {
|
|||||||
/// This is the main I/O error, for further details check the error kind and additional context.
|
/// This is the main I/O error, for further details check the error kind and additional context.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
#[diagnostic(transparent)]
|
#[diagnostic(transparent)]
|
||||||
Io(io::IoError),
|
Io(#[from] io::IoError),
|
||||||
|
|
||||||
/// A name was not found. Did you mean a different name?
|
/// A name was not found. Did you mean a different name?
|
||||||
///
|
///
|
||||||
@ -1381,60 +1383,9 @@ On Windows, this would be %USERPROFILE%\AppData\Roaming"#
|
|||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("Job {id} not found")]
|
#[error(transparent)]
|
||||||
#[diagnostic(
|
#[diagnostic(transparent)]
|
||||||
code(nu::shell::job_not_found),
|
Job(#[from] JobError),
|
||||||
help(
|
|
||||||
"The operation could not be completed, there is no job currently running with this id"
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
JobNotFound {
|
|
||||||
id: usize,
|
|
||||||
#[label = "job not found"]
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("No frozen job to unfreeze")]
|
|
||||||
#[diagnostic(
|
|
||||||
code(nu::shell::no_frozen_job),
|
|
||||||
help("There is currently no frozen job to unfreeze")
|
|
||||||
)]
|
|
||||||
NoFrozenJob {
|
|
||||||
#[label = "no frozen job"]
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("Job {id} is not frozen")]
|
|
||||||
#[diagnostic(
|
|
||||||
code(nu::shell::job_not_frozen),
|
|
||||||
help("You tried to unfreeze a job which is not frozen")
|
|
||||||
)]
|
|
||||||
JobNotFrozen {
|
|
||||||
id: usize,
|
|
||||||
#[label = "job not frozen"]
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("The job {id} is frozen")]
|
|
||||||
#[diagnostic(
|
|
||||||
code(nu::shell::job_is_frozen),
|
|
||||||
help("This operation cannot be performed because the job is frozen")
|
|
||||||
)]
|
|
||||||
JobIsFrozen {
|
|
||||||
id: usize,
|
|
||||||
#[label = "This job is frozen"]
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error("No message was received in the requested time interval")]
|
|
||||||
#[diagnostic(
|
|
||||||
code(nu::shell::recv_timeout),
|
|
||||||
help("No message arrived within the specified time limit")
|
|
||||||
)]
|
|
||||||
RecvTimeout {
|
|
||||||
#[label = "timeout"]
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
#[diagnostic(transparent)]
|
#[diagnostic(transparent)]
|
||||||
|
@ -37,6 +37,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<M> Id<M, usize> {
|
||||||
|
pub const ZERO: Self = Self::new(0);
|
||||||
|
}
|
||||||
|
|
||||||
impl<M, V> Debug for Id<M, V>
|
impl<M, V> Debug for Id<M, V>
|
||||||
where
|
where
|
||||||
V: Display,
|
V: Display,
|
||||||
@ -115,6 +119,12 @@ pub type JobId = Id<marker::Job>;
|
|||||||
/// Note: `%0` is allocated with the block input at the beginning of a compiled block.
|
/// Note: `%0` is allocated with the block input at the beginning of a compiled block.
|
||||||
pub type RegId = Id<marker::Reg, u32>;
|
pub type RegId = Id<marker::Reg, u32>;
|
||||||
|
|
||||||
|
impl Display for JobId {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for RegId {
|
impl Display for RegId {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "%{}", self.get())
|
write!(f, "%{}", self.get())
|
||||||
|
Reference in New Issue
Block a user