mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 15:25:06 +02:00
Refactor: Construct IoError
from std::io::Error
instead of std::io::ErrorKind
(#15777)
This commit is contained in:
@ -77,7 +77,7 @@ impl Command for BytesEndsWith {
|
||||
Ok(&[]) => break,
|
||||
Ok(buf) => buf,
|
||||
Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
|
||||
Err(e) => return Err(IoError::new(e.kind(), span, None).into()),
|
||||
Err(e) => return Err(IoError::new(e, span, None).into()),
|
||||
};
|
||||
let len = buf.len();
|
||||
if len >= cap {
|
||||
|
@ -72,7 +72,7 @@ impl Command for BytesStartsWith {
|
||||
reader
|
||||
.take(pattern.len() as u64)
|
||||
.read_to_end(&mut start)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
|
||||
Ok(Value::bool(start == pattern, head).into_pipeline_data())
|
||||
} else {
|
||||
|
@ -41,12 +41,11 @@ impl SQLiteDatabase {
|
||||
}
|
||||
|
||||
pub fn try_from_path(path: &Path, span: Span, signals: Signals) -> Result<Self, ShellError> {
|
||||
let mut file =
|
||||
File::open(path).map_err(|e| IoError::new(e.kind(), span, PathBuf::from(path)))?;
|
||||
let mut file = File::open(path).map_err(|e| IoError::new(e, span, PathBuf::from(path)))?;
|
||||
|
||||
let mut buf: [u8; 16] = [0; 16];
|
||||
file.read_exact(&mut buf)
|
||||
.map_err(|e| ShellError::Io(IoError::new(e.kind(), span, PathBuf::from(path))))
|
||||
.map_err(|e| ShellError::Io(IoError::new(e, span, PathBuf::from(path))))
|
||||
.and_then(|_| {
|
||||
if buf == SQLITE_MAGIC_BYTES {
|
||||
Ok(SQLiteDatabase::new(path, signals))
|
||||
|
2
crates/nu-command/src/env/config/config_.rs
vendored
2
crates/nu-command/src/env/config/config_.rs
vendored
@ -115,7 +115,7 @@ pub(super) fn start_editor(
|
||||
|
||||
let child = child.map_err(|err| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
err,
|
||||
call.head,
|
||||
None,
|
||||
"Could not spawn foreground child",
|
||||
|
@ -59,7 +59,7 @@ impl Command for ConfigReset {
|
||||
));
|
||||
if let Err(err) = std::fs::rename(nu_config.clone(), &backup_path) {
|
||||
return Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
err.kind().not_found_as(NotFound::Directory),
|
||||
err.not_found_as(NotFound::Directory),
|
||||
span,
|
||||
PathBuf::from(backup_path),
|
||||
"config.nu could not be backed up",
|
||||
@ -69,7 +69,7 @@ impl Command for ConfigReset {
|
||||
if let Ok(mut file) = std::fs::File::create(&nu_config) {
|
||||
if let Err(err) = writeln!(&mut file, "{config_file}") {
|
||||
return Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
err.kind().not_found_as(NotFound::File),
|
||||
err.not_found_as(NotFound::File),
|
||||
span,
|
||||
PathBuf::from(nu_config),
|
||||
"config.nu could not be written to",
|
||||
@ -86,7 +86,7 @@ impl Command for ConfigReset {
|
||||
backup_path.push(format!("oldenv-{}.nu", Local::now().format("%F-%H-%M-%S"),));
|
||||
if let Err(err) = std::fs::rename(env_config.clone(), &backup_path) {
|
||||
return Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
err.kind().not_found_as(NotFound::Directory),
|
||||
err.not_found_as(NotFound::Directory),
|
||||
span,
|
||||
PathBuf::from(backup_path),
|
||||
"env.nu could not be backed up",
|
||||
@ -96,7 +96,7 @@ impl Command for ConfigReset {
|
||||
if let Ok(mut file) = std::fs::File::create(&env_config) {
|
||||
if let Err(err) = writeln!(&mut file, "{config_file}") {
|
||||
return Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
err.kind().not_found_as(NotFound::File),
|
||||
err.not_found_as(NotFound::File),
|
||||
span,
|
||||
PathBuf::from(env_config),
|
||||
"env.nu could not be written to",
|
||||
|
8
crates/nu-command/src/env/source_env.rs
vendored
8
crates/nu-command/src/env/source_env.rs
vendored
@ -2,7 +2,11 @@ use nu_engine::{
|
||||
command_prelude::*, find_in_dirs_env, get_dirs_var_from_call, get_eval_block_with_early_return,
|
||||
redirect_env,
|
||||
};
|
||||
use nu_protocol::{BlockId, engine::CommandType, shell_error::io::IoError};
|
||||
use nu_protocol::{
|
||||
BlockId,
|
||||
engine::CommandType,
|
||||
shell_error::{self, io::IoError},
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Source a file for environment variables.
|
||||
@ -66,7 +70,7 @@ impl Command for SourceEnv {
|
||||
PathBuf::from(&path)
|
||||
} else {
|
||||
return Err(ShellError::Io(IoError::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
shell_error::io::ErrorKind::FileNotFound,
|
||||
source_filename.span,
|
||||
PathBuf::from(source_filename.item),
|
||||
)));
|
||||
|
@ -53,7 +53,7 @@ impl Command for JobKill {
|
||||
|
||||
jobs.kill_and_remove(id).map_err(|err| {
|
||||
ShellError::Io(IoError::new_internal(
|
||||
err.kind(),
|
||||
err,
|
||||
"Failed to kill the requested job",
|
||||
nu_protocol::location!(),
|
||||
))
|
||||
|
@ -121,7 +121,7 @@ impl Command for JobSpawn {
|
||||
Err(err) => {
|
||||
jobs.remove_job(id);
|
||||
Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
err,
|
||||
call.head,
|
||||
None,
|
||||
"Failed to spawn thread for job",
|
||||
|
@ -3,7 +3,6 @@ use nu_protocol::{
|
||||
JobId,
|
||||
engine::{FrozenJob, Job, ThreadJob},
|
||||
process::check_ok,
|
||||
shell_error,
|
||||
};
|
||||
use nu_system::{ForegroundWaitStatus, kill_by_pid};
|
||||
|
||||
@ -123,7 +122,7 @@ fn unfreeze_job(
|
||||
if !thread_job.try_add_pid(pid) {
|
||||
kill_by_pid(pid.into()).map_err(|err| {
|
||||
ShellError::Io(IoError::new_internal(
|
||||
err.kind(),
|
||||
err,
|
||||
"job was interrupted; could not kill foreground process",
|
||||
nu_protocol::location!(),
|
||||
))
|
||||
@ -163,7 +162,7 @@ fn unfreeze_job(
|
||||
Ok(ForegroundWaitStatus::Finished(status)) => check_ok(status, false, span),
|
||||
|
||||
Err(err) => Err(ShellError::Io(IoError::new_internal(
|
||||
shell_error::io::ErrorKind::Std(err.kind()),
|
||||
err,
|
||||
"Failed to unfreeze foreground process",
|
||||
nu_protocol::location!(),
|
||||
))),
|
||||
|
@ -77,7 +77,7 @@ impl Command for Cd {
|
||||
if let Ok(path) = nu_path::canonicalize_with(path_no_whitespace, &cwd) {
|
||||
if !path.is_dir() {
|
||||
return Err(shell_error::io::IoError::new(
|
||||
shell_error::io::ErrorKind::Std(
|
||||
shell_error::io::ErrorKind::from_std(
|
||||
std::io::ErrorKind::NotADirectory,
|
||||
),
|
||||
v.span,
|
||||
@ -106,7 +106,9 @@ impl Command for Cd {
|
||||
};
|
||||
if !path.is_dir() {
|
||||
return Err(shell_error::io::IoError::new(
|
||||
shell_error::io::ErrorKind::Std(std::io::ErrorKind::NotADirectory),
|
||||
shell_error::io::ErrorKind::from_std(
|
||||
std::io::ErrorKind::NotADirectory,
|
||||
),
|
||||
v.span,
|
||||
path,
|
||||
)
|
||||
@ -132,9 +134,12 @@ impl Command for Cd {
|
||||
stack.set_cwd(path)?;
|
||||
Ok(PipelineData::empty())
|
||||
}
|
||||
PermissionResult::PermissionDenied => {
|
||||
Err(IoError::new(std::io::ErrorKind::PermissionDenied, call.head, path).into())
|
||||
}
|
||||
PermissionResult::PermissionDenied => Err(IoError::new(
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::PermissionDenied),
|
||||
call.head,
|
||||
path,
|
||||
)
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,10 @@ use nu_engine::glob_from;
|
||||
use nu_engine::{command_prelude::*, env::current_dir};
|
||||
use nu_glob::MatchOptions;
|
||||
use nu_path::{expand_path_with, expand_to_real_path};
|
||||
use nu_protocol::{DataSource, NuGlob, PipelineMetadata, Signals, shell_error::io::IoError};
|
||||
use nu_protocol::{
|
||||
DataSource, NuGlob, PipelineMetadata, Signals,
|
||||
shell_error::{self, io::IoError},
|
||||
};
|
||||
use pathdiff::diff_paths;
|
||||
use rayon::prelude::*;
|
||||
#[cfg(unix)]
|
||||
@ -252,7 +255,7 @@ fn ls_for_one_pattern(
|
||||
// it makes no sense to list an empty string.
|
||||
if path.item.as_ref().is_empty() {
|
||||
return Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::NotFound,
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::NotFound),
|
||||
path.span,
|
||||
PathBuf::from(path.item.to_string()),
|
||||
"empty string('') directory or file does not exist",
|
||||
@ -357,7 +360,7 @@ fn ls_for_one_pattern(
|
||||
let count = std::thread::available_parallelism()
|
||||
.map_err(|err| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
err,
|
||||
call_span,
|
||||
None,
|
||||
"Could not get available parallelism",
|
||||
@ -793,6 +796,7 @@ fn unix_time_to_local_date_time(secs: i64) -> Option<DateTime<Local>> {
|
||||
mod windows_helper {
|
||||
use super::*;
|
||||
|
||||
use nu_protocol::shell_error;
|
||||
use std::os::windows::prelude::OsStrExt;
|
||||
use windows::Win32::Foundation::FILETIME;
|
||||
use windows::Win32::Storage::FileSystem::{
|
||||
@ -928,7 +932,7 @@ mod windows_helper {
|
||||
Ok(find_data)
|
||||
}
|
||||
Err(e) => Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::Other,
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::Other),
|
||||
span,
|
||||
PathBuf::from(filename),
|
||||
format!("Could not read metadata: {e}"),
|
||||
@ -973,11 +977,11 @@ fn read_dir(
|
||||
let signals_clone = signals.clone();
|
||||
let items = f
|
||||
.read_dir()
|
||||
.map_err(|err| IoError::new(err.kind(), span, f.clone()))?
|
||||
.map_err(|err| IoError::new(err, span, f.clone()))?
|
||||
.map(move |d| {
|
||||
signals_clone.check(span)?;
|
||||
d.map(|r| r.path())
|
||||
.map_err(|err| IoError::new(err.kind(), span, f.clone()))
|
||||
.map_err(|err| IoError::new(err, span, f.clone()))
|
||||
.map_err(ShellError::from)
|
||||
});
|
||||
if !use_threads {
|
||||
|
@ -121,7 +121,7 @@ impl Command for Open {
|
||||
|
||||
if permission_denied(path) {
|
||||
let err = IoError::new(
|
||||
std::io::ErrorKind::PermissionDenied,
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::PermissionDenied),
|
||||
arg_span,
|
||||
PathBuf::from(path),
|
||||
);
|
||||
@ -162,14 +162,18 @@ impl Command for Open {
|
||||
// At least under windows this check ensures that we don't get a
|
||||
// permission denied error on directories
|
||||
return Err(ShellError::Io(IoError::new(
|
||||
shell_error::io::ErrorKind::Std(std::io::ErrorKind::IsADirectory),
|
||||
#[allow(
|
||||
deprecated,
|
||||
reason = "we don't have a IsADirectory variant here, so we provide one"
|
||||
)]
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::IsADirectory),
|
||||
arg_span,
|
||||
PathBuf::from(path),
|
||||
)));
|
||||
}
|
||||
|
||||
let file = std::fs::File::open(path)
|
||||
.map_err(|err| IoError::new(err.kind(), arg_span, PathBuf::from(path)))?;
|
||||
.map_err(|err| IoError::new(err, arg_span, PathBuf::from(path)))?;
|
||||
|
||||
// No content_type by default - Is added later if no converter is found
|
||||
let stream = PipelineData::ByteStream(
|
||||
|
@ -304,7 +304,7 @@ fn rm(
|
||||
&& matches!(
|
||||
e,
|
||||
ShellError::Io(IoError {
|
||||
kind: shell_error::io::ErrorKind::Std(std::io::ErrorKind::NotFound),
|
||||
kind: shell_error::io::ErrorKind::Std(std::io::ErrorKind::NotFound, ..),
|
||||
..
|
||||
})
|
||||
))
|
||||
@ -420,7 +420,7 @@ fn rm(
|
||||
};
|
||||
|
||||
if let Err(e) = result {
|
||||
Err(ShellError::Io(IoError::new(e.kind(), span, f)))
|
||||
Err(ShellError::Io(IoError::new(e, span, f)))
|
||||
} else if verbose {
|
||||
let msg = if interactive && !confirmed {
|
||||
"not deleted"
|
||||
|
@ -130,7 +130,7 @@ impl Command for Save {
|
||||
io::copy(&mut tee, &mut io::stderr())
|
||||
}
|
||||
}
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -428,20 +428,24 @@ fn open_file(path: &Path, span: Span, append: bool) -> Result<File, ShellError>
|
||||
(true, true) => std::fs::OpenOptions::new()
|
||||
.append(true)
|
||||
.open(path)
|
||||
.map_err(|err| err.kind().into()),
|
||||
.map_err(|err| err.into()),
|
||||
_ => {
|
||||
// This is a temporary solution until `std::fs::File::create` is fixed on Windows (rust-lang/rust#134893)
|
||||
// A TOCTOU problem exists here, which may cause wrong error message to be shown
|
||||
#[cfg(target_os = "windows")]
|
||||
if path.is_dir() {
|
||||
Err(nu_protocol::shell_error::io::ErrorKind::Std(
|
||||
#[allow(
|
||||
deprecated,
|
||||
reason = "we don't get a IsADirectory error, so we need to provide it"
|
||||
)]
|
||||
Err(nu_protocol::shell_error::io::ErrorKind::from_std(
|
||||
std::io::ErrorKind::IsADirectory,
|
||||
))
|
||||
} else {
|
||||
std::fs::File::create(path).map_err(|err| err.kind().into())
|
||||
std::fs::File::create(path).map_err(|err| err.into())
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
std::fs::File::create(path).map_err(|err| err.kind().into())
|
||||
std::fs::File::create(path).map_err(|err| err.into())
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
#[allow(deprecated)]
|
||||
use nu_engine::{command_prelude::*, current_dir};
|
||||
use nu_protocol::{NuGlob, shell_error::io::IoError};
|
||||
use nu_protocol::{
|
||||
NuGlob,
|
||||
shell_error::{self, io::IoError},
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
use uu_cp::{BackupMode, CopyMode, UpdateMode};
|
||||
|
||||
@ -198,7 +201,7 @@ impl Command for UCp {
|
||||
.collect();
|
||||
if exp_files.is_empty() {
|
||||
return Err(ShellError::Io(IoError::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
shell_error::io::ErrorKind::FileNotFound,
|
||||
p.span,
|
||||
PathBuf::from(p.item.to_string()),
|
||||
)));
|
||||
|
@ -1,7 +1,10 @@
|
||||
#[allow(deprecated)]
|
||||
use nu_engine::{command_prelude::*, current_dir};
|
||||
use nu_path::expand_path_with;
|
||||
use nu_protocol::{NuGlob, shell_error::io::IoError};
|
||||
use nu_protocol::{
|
||||
NuGlob,
|
||||
shell_error::{self, io::IoError},
|
||||
};
|
||||
use std::{ffi::OsString, path::PathBuf};
|
||||
use uu_mv::{BackupMode, UpdateMode};
|
||||
|
||||
@ -139,7 +142,7 @@ impl Command for UMv {
|
||||
.collect();
|
||||
if exp_files.is_empty() {
|
||||
return Err(ShellError::Io(IoError::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
shell_error::io::ErrorKind::FileNotFound,
|
||||
p.span,
|
||||
PathBuf::from(p.item.to_string()),
|
||||
)));
|
||||
|
@ -227,7 +227,7 @@ impl Command for UTouch {
|
||||
TouchError::ReferenceFileInaccessible(reference_path, io_err) => {
|
||||
let span = reference_span.expect("touch should've been given a reference file");
|
||||
ShellError::Io(IoError::new_with_additional_context(
|
||||
io_err.kind(),
|
||||
io_err,
|
||||
span,
|
||||
reference_path,
|
||||
"failed to read metadata",
|
||||
|
@ -86,7 +86,7 @@ impl Command for Watch {
|
||||
Ok(p) => p,
|
||||
Err(err) => {
|
||||
return Err(ShellError::Io(IoError::new(
|
||||
err.kind(),
|
||||
err,
|
||||
path_arg.span,
|
||||
PathBuf::from(path_no_whitespace),
|
||||
)));
|
||||
|
@ -37,7 +37,7 @@ pub fn empty(
|
||||
.bytes()
|
||||
.next()
|
||||
.transpose()
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?
|
||||
.map_err(|err| IoError::new(err, span, None))?
|
||||
.is_none();
|
||||
if negate {
|
||||
Ok(Value::bool(!is_empty, head).into_pipeline_data())
|
||||
|
@ -182,7 +182,7 @@ fn first_helper(
|
||||
let mut byte = [0u8];
|
||||
if reader
|
||||
.read(&mut byte)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?
|
||||
.map_err(|err| IoError::new(err, span, None))?
|
||||
> 0
|
||||
{
|
||||
Ok(Value::int(byte[0] as i64, head).into_pipeline_data())
|
||||
|
@ -137,7 +137,7 @@ interleave
|
||||
}
|
||||
})
|
||||
.map(|_| ())
|
||||
.map_err(|err| IoError::new(err.kind(), head, None).into())
|
||||
.map_err(|err| IoError::new(err, head, None).into())
|
||||
})
|
||||
})?;
|
||||
|
||||
|
@ -166,7 +166,7 @@ impl Command for Last {
|
||||
let mut buf = VecDeque::with_capacity(rows + TAKE as usize);
|
||||
loop {
|
||||
let taken = std::io::copy(&mut (&mut reader).take(TAKE), &mut buf)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
if buf.len() > rows {
|
||||
buf.drain(..(buf.len() - rows));
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use nu_engine::{command_prelude::*, get_eval_block_with_early_return};
|
||||
#[cfg(feature = "os")]
|
||||
use nu_protocol::process::ChildPipe;
|
||||
#[cfg(test)]
|
||||
use nu_protocol::shell_error;
|
||||
use nu_protocol::{
|
||||
ByteStream, ByteStreamSource, OutDest, PipelineMetadata, Signals,
|
||||
byte_stream::copy_with_signals, engine::Closure, report_shell_error, shell_error::io::IoError,
|
||||
@ -440,7 +442,7 @@ fn spawn_tee(
|
||||
eval_block(PipelineData::ByteStream(stream, info.metadata))
|
||||
})
|
||||
.map_err(|err| {
|
||||
IoError::new_with_additional_context(err.kind(), info.span, None, "Could not spawn tee")
|
||||
IoError::new_with_additional_context(err, info.span, None, "Could not spawn tee")
|
||||
})?;
|
||||
|
||||
Ok(TeeThread { sender, thread })
|
||||
@ -481,13 +483,8 @@ fn copy_on_thread(
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|err| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
span,
|
||||
None,
|
||||
"Could not spawn stderr copier",
|
||||
)
|
||||
.into()
|
||||
IoError::new_with_additional_context(err, span, None, "Could not spawn stderr copier")
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
@ -532,7 +529,7 @@ fn tee_forwards_errors_back_immediately() {
|
||||
let slow_input = (0..100).inspect(|_| std::thread::sleep(Duration::from_millis(1)));
|
||||
let iter = tee(slow_input, |_| {
|
||||
Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::Other,
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::Other),
|
||||
Span::test_data(),
|
||||
None,
|
||||
"test",
|
||||
@ -564,7 +561,7 @@ fn tee_waits_for_the_other_thread() {
|
||||
std::thread::sleep(Duration::from_millis(10));
|
||||
waited_clone.store(true, Ordering::Relaxed);
|
||||
Err(ShellError::Io(IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::Other,
|
||||
shell_error::io::ErrorKind::from_std(std::io::ErrorKind::Other),
|
||||
Span::test_data(),
|
||||
None,
|
||||
"test",
|
||||
|
@ -134,7 +134,7 @@ fn read_json_lines(
|
||||
.lines()
|
||||
.filter(|line| line.as_ref().is_ok_and(|line| !line.trim().is_empty()) || line.is_err())
|
||||
.map(move |line| {
|
||||
let line = line.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
let line = line.map_err(|err| IoError::new(err, span, None))?;
|
||||
if strict {
|
||||
convert_string_to_value_strict(&line, span)
|
||||
} else {
|
||||
|
@ -8,7 +8,7 @@ use std::{iter, sync::Arc};
|
||||
|
||||
fn make_csv_error(error: csv::Error, format_name: &str, head: Span) -> ShellError {
|
||||
if let csv::ErrorKind::Io(error) = error.kind() {
|
||||
IoError::new(error.kind(), head, None).into()
|
||||
IoError::new(error, head, None).into()
|
||||
} else {
|
||||
ShellError::GenericError {
|
||||
error: format!("Failed to generate {format_name} data"),
|
||||
|
@ -152,7 +152,7 @@ impl From<WriteError> for ShellError {
|
||||
help: None,
|
||||
inner: vec![],
|
||||
},
|
||||
WriteError::Io(err, span) => ShellError::Io(IoError::new(err.kind(), span, None)),
|
||||
WriteError::Io(err, span) => ShellError::Io(IoError::new(err, span, None)),
|
||||
WriteError::Shell(err) => *err,
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ impl Command for ToMsgpackz {
|
||||
serialize_types,
|
||||
)?;
|
||||
out.flush()
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
drop(out);
|
||||
|
||||
Ok(Value::binary(out_buf, call.head).into_pipeline_data())
|
||||
|
@ -55,13 +55,8 @@ impl Command for Source {
|
||||
let cwd = engine_state.cwd_as_string(Some(stack))?;
|
||||
let pb = std::path::PathBuf::from(block_id_name);
|
||||
let parent = pb.parent().unwrap_or(std::path::Path::new(""));
|
||||
let file_path = canonicalize_with(pb.as_path(), cwd).map_err(|err| {
|
||||
IoError::new(
|
||||
err.kind().not_found_as(NotFound::File),
|
||||
call.head,
|
||||
pb.clone(),
|
||||
)
|
||||
})?;
|
||||
let file_path = canonicalize_with(pb.as_path(), cwd)
|
||||
.map_err(|err| IoError::new(err.not_found_as(NotFound::File), call.head, pb.clone()))?;
|
||||
|
||||
// Note: We intentionally left out PROCESS_PATH since it's supposed to
|
||||
// to work like argv[0] in C, which is the name of the program being executed.
|
||||
|
@ -374,9 +374,7 @@ fn send_multipart_request(
|
||||
let mut builder = MultipartWriter::new();
|
||||
|
||||
let err = |e: std::io::Error| {
|
||||
ShellErrorOrRequestError::ShellError(
|
||||
IoError::new_with_additional_context(e.kind(), span, None, e).into(),
|
||||
)
|
||||
ShellErrorOrRequestError::ShellError(IoError::new(e, span, None).into())
|
||||
};
|
||||
|
||||
for (col, val) in val.into_owned() {
|
||||
@ -466,12 +464,7 @@ fn send_cancellable_request(
|
||||
let _ = tx.send(ret); // may fail if the user has cancelled the operation
|
||||
})
|
||||
.map_err(|err| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
span,
|
||||
None,
|
||||
"Could not spawn HTTP requester",
|
||||
)
|
||||
IoError::new_with_additional_context(err, span, None, "Could not spawn HTTP requester")
|
||||
})
|
||||
.map_err(ShellError::from)?;
|
||||
|
||||
@ -529,12 +522,7 @@ fn send_cancellable_request_bytes(
|
||||
let _ = tx.send(ret);
|
||||
})
|
||||
.map_err(|err| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
span,
|
||||
None,
|
||||
"Could not spawn HTTP requester",
|
||||
)
|
||||
IoError::new_with_additional_context(err, span, None, "Could not spawn HTTP requester")
|
||||
})
|
||||
.map_err(ShellError::from)?;
|
||||
|
||||
@ -685,7 +673,7 @@ fn handle_response_error(span: Span, requested_url: &str, response_err: Error) -
|
||||
break 'io generic_network_failure();
|
||||
};
|
||||
|
||||
ShellError::Io(IoError::new(io_error.kind(), span, None))
|
||||
ShellError::Io(IoError::new(io_error, span, None))
|
||||
}
|
||||
_ => generic_network_failure(),
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ fn get_free_port(
|
||||
}
|
||||
|
||||
Err(IoError::new_with_additional_context(
|
||||
last_err.expect("range not empty, validated before").kind(),
|
||||
last_err.expect("range not empty, validated before"),
|
||||
range_span,
|
||||
None,
|
||||
"Every port has been tried, but no valid one was found",
|
||||
|
@ -153,7 +153,7 @@ fn exists(path: &Path, span: Span, args: &Arguments) -> Value {
|
||||
Value::bool(
|
||||
match exists {
|
||||
Ok(exists) => exists,
|
||||
Err(err) => return Value::error(IoError::new(err.kind(), span, path).into(), span),
|
||||
Err(err) => return Value::error(IoError::new(err, span, path).into(), span),
|
||||
},
|
||||
span,
|
||||
)
|
||||
|
@ -1,6 +1,9 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_path::expand_path_with;
|
||||
use nu_protocol::{engine::StateWorkingSet, shell_error::io::IoError};
|
||||
use nu_protocol::{
|
||||
engine::StateWorkingSet,
|
||||
shell_error::{self, io::IoError},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PathSelf;
|
||||
@ -56,7 +59,7 @@ impl Command for PathSelf {
|
||||
let cwd = working_set.permanent_state.cwd(None)?;
|
||||
let current_file = working_set.files.top().ok_or_else(|| {
|
||||
IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::NotFound,
|
||||
shell_error::io::ErrorKind::FileNotFound,
|
||||
call.head,
|
||||
None,
|
||||
"Couldn't find current file",
|
||||
@ -67,7 +70,7 @@ impl Command for PathSelf {
|
||||
let dir = expand_path_with(
|
||||
current_file.parent().ok_or_else(|| {
|
||||
IoError::new_with_additional_context(
|
||||
std::io::ErrorKind::NotFound,
|
||||
shell_error::io::ErrorKind::FileNotFound,
|
||||
call.head,
|
||||
current_file.to_owned(),
|
||||
"Couldn't find current file's parent.",
|
||||
|
@ -108,7 +108,7 @@ fn path_type(path: &Path, span: Span, args: &Arguments) -> Value {
|
||||
match path.symlink_metadata() {
|
||||
Ok(metadata) => Value::string(get_file_type(&metadata), span),
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => Value::nothing(span),
|
||||
Err(err) => Value::error(IoError::new(err.kind(), span, None).into(), span),
|
||||
Err(err) => Value::error(IoError::new(err, span, None).into(), span),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ impl FileInfo {
|
||||
long,
|
||||
})
|
||||
}
|
||||
Err(e) => Err(IoError::new(e.kind(), tag, path).into()),
|
||||
Err(e) => Err(IoError::new(e, tag, path).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crossterm::{
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::shell_error::io::IoError;
|
||||
use nu_protocol::shell_error::{self, io::IoError};
|
||||
|
||||
use std::{io::Write, time::Duration};
|
||||
|
||||
@ -116,7 +116,9 @@ impl Command for Input {
|
||||
crossterm::terminal::disable_raw_mode()
|
||||
.map_err(&from_io_error)?;
|
||||
return Err(IoError::new(
|
||||
std::io::ErrorKind::Interrupted,
|
||||
shell_error::io::ErrorKind::from_std(
|
||||
std::io::ErrorKind::Interrupted,
|
||||
),
|
||||
call.head,
|
||||
None,
|
||||
)
|
||||
@ -156,7 +158,7 @@ impl Command for Input {
|
||||
terminal::Clear(ClearType::CurrentLine),
|
||||
cursor::MoveToColumn(0),
|
||||
)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
if let Some(prompt) = &prompt {
|
||||
execute!(std::io::stdout(), Print(prompt.to_string()))
|
||||
.map_err(&from_io_error)?;
|
||||
|
@ -84,7 +84,7 @@ There are 4 `key_type` variants:
|
||||
let add_raw = call.has_flag(engine_state, stack, "raw")?;
|
||||
let config = engine_state.get_config();
|
||||
|
||||
terminal::enable_raw_mode().map_err(|err| IoError::new(err.kind(), head, None))?;
|
||||
terminal::enable_raw_mode().map_err(|err| IoError::new(err, head, None))?;
|
||||
|
||||
if config.use_kitty_protocol {
|
||||
if let Ok(false) = crossterm::terminal::supports_keyboard_enhancement() {
|
||||
@ -123,7 +123,7 @@ There are 4 `key_type` variants:
|
||||
})?;
|
||||
let event = parse_event(head, &event, &event_type_filter, add_raw);
|
||||
if let Some(event) = event {
|
||||
terminal::disable_raw_mode().map_err(|err| IoError::new(err.kind(), head, None))?;
|
||||
terminal::disable_raw_mode().map_err(|err| IoError::new(err, head, None))?;
|
||||
if config.use_kitty_protocol {
|
||||
let _ = execute!(
|
||||
std::io::stdout(),
|
||||
@ -230,17 +230,17 @@ impl EventTypeFilter {
|
||||
fn enable_events(&self, span: Span) -> Result<DeferredConsoleRestore, ShellError> {
|
||||
if self.listen_mouse {
|
||||
crossterm::execute!(stdout(), EnableMouseCapture)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
}
|
||||
|
||||
if self.listen_paste {
|
||||
crossterm::execute!(stdout(), EnableBracketedPaste)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
}
|
||||
|
||||
if self.listen_focus {
|
||||
crossterm::execute!(stdout(), crossterm::event::EnableFocusChange)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
}
|
||||
|
||||
Ok(DeferredConsoleRestore {
|
||||
|
@ -142,12 +142,7 @@ impl Command for InputList {
|
||||
.report(false)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.map_err(|dialoguer::Error::IO(err)| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
call.head,
|
||||
None,
|
||||
INTERACT_ERROR,
|
||||
)
|
||||
IoError::new_with_additional_context(err, call.head, None, INTERACT_ERROR)
|
||||
})?,
|
||||
)
|
||||
} else if fuzzy {
|
||||
@ -164,12 +159,7 @@ impl Command for InputList {
|
||||
.report(false)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.map_err(|dialoguer::Error::IO(err)| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
call.head,
|
||||
None,
|
||||
INTERACT_ERROR,
|
||||
)
|
||||
IoError::new_with_additional_context(err, call.head, None, INTERACT_ERROR)
|
||||
})?,
|
||||
)
|
||||
} else {
|
||||
@ -185,12 +175,7 @@ impl Command for InputList {
|
||||
.report(false)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.map_err(|dialoguer::Error::IO(err)| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
call.head,
|
||||
None,
|
||||
INTERACT_ERROR,
|
||||
)
|
||||
IoError::new_with_additional_context(err, call.head, None, INTERACT_ERROR)
|
||||
})?,
|
||||
)
|
||||
};
|
||||
|
@ -99,19 +99,17 @@ The `prefix` is not included in the output."
|
||||
let prefix = prefix.unwrap_or_default();
|
||||
let terminator: Option<Vec<u8>> = call.get_flag(engine_state, stack, "terminator")?;
|
||||
|
||||
crossterm::terminal::enable_raw_mode()
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
crossterm::terminal::enable_raw_mode().map_err(|err| IoError::new(err, call.head, None))?;
|
||||
scopeguard::defer! {
|
||||
let _ = crossterm::terminal::disable_raw_mode();
|
||||
}
|
||||
|
||||
// clear terminal events
|
||||
while crossterm::event::poll(Duration::from_secs(0))
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?
|
||||
.map_err(|err| IoError::new(err, call.head, None))?
|
||||
{
|
||||
// If there's an event, read it to remove it from the queue
|
||||
let _ = crossterm::event::read()
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
let _ = crossterm::event::read().map_err(|err| IoError::new(err, call.head, None))?;
|
||||
}
|
||||
|
||||
let mut b = [0u8; 1];
|
||||
@ -122,17 +120,17 @@ The `prefix` is not included in the output."
|
||||
let mut stdout = std::io::stdout().lock();
|
||||
stdout
|
||||
.write_all(&query)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
stdout
|
||||
.flush()
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
}
|
||||
|
||||
// Validate and skip prefix
|
||||
for bc in prefix {
|
||||
stdin
|
||||
.read_exact(&mut b)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
if b[0] != bc {
|
||||
return Err(ShellError::GenericError {
|
||||
error: "Input did not begin with expected sequence".into(),
|
||||
@ -151,7 +149,7 @@ The `prefix` is not included in the output."
|
||||
loop {
|
||||
stdin
|
||||
.read_exact(&mut b)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
|
||||
if b[0] == CTRL_C {
|
||||
return Err(ShellError::InterruptedByUser {
|
||||
@ -173,7 +171,7 @@ The `prefix` is not included in the output."
|
||||
loop {
|
||||
stdin
|
||||
.read_exact(&mut b)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
.map_err(|err| IoError::new(err, call.head, None))?;
|
||||
|
||||
if b[0] == CTRL_C {
|
||||
break;
|
||||
|
@ -255,7 +255,7 @@ fn parse_file_script(
|
||||
match std::fs::read(path) {
|
||||
Ok(contents) => parse_script(working_set, Some(&filename), &contents, is_debug, call_head),
|
||||
Err(err) => Err(ShellError::Io(IoError::new(
|
||||
err.kind().not_found_as(NotFound::File),
|
||||
err.not_found_as(NotFound::File),
|
||||
path_span,
|
||||
PathBuf::from(path),
|
||||
))),
|
||||
|
@ -93,7 +93,7 @@ fn registry_query(
|
||||
let reg_hive = get_reg_hive(engine_state, stack, call)?;
|
||||
let reg_key = reg_hive
|
||||
.open_subkey(registry_key.item)
|
||||
.map_err(|err| IoError::new(err.kind(), *registry_key_span, None))?;
|
||||
.map_err(|err| IoError::new(err, *registry_key_span, None))?;
|
||||
|
||||
if registry_value.is_none() {
|
||||
let mut reg_values = vec![];
|
||||
|
@ -205,11 +205,11 @@ impl Command for External {
|
||||
let stderr = stack.stderr();
|
||||
let merged_stream = if matches!(stdout, OutDest::Pipe) && matches!(stderr, OutDest::Pipe) {
|
||||
let (reader, writer) =
|
||||
os_pipe::pipe().map_err(|err| IoError::new(err.kind(), call.head, None))?;
|
||||
os_pipe::pipe().map_err(|err| IoError::new(err, call.head, None))?;
|
||||
command.stdout(
|
||||
writer
|
||||
.try_clone()
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?,
|
||||
.map_err(|err| IoError::new(err, call.head, None))?,
|
||||
);
|
||||
command.stderr(writer);
|
||||
Some(reader)
|
||||
@ -220,8 +220,7 @@ impl Command for External {
|
||||
command.stdout(Stdio::null());
|
||||
} else {
|
||||
command.stdout(
|
||||
Stdio::try_from(stdout)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?,
|
||||
Stdio::try_from(stdout).map_err(|err| IoError::new(err, call.head, None))?,
|
||||
);
|
||||
}
|
||||
|
||||
@ -231,8 +230,7 @@ impl Command for External {
|
||||
command.stderr(Stdio::null());
|
||||
} else {
|
||||
command.stderr(
|
||||
Stdio::try_from(stderr)
|
||||
.map_err(|err| IoError::new(err.kind(), call.head, None))?,
|
||||
Stdio::try_from(stderr).map_err(|err| IoError::new(err, call.head, None))?,
|
||||
);
|
||||
}
|
||||
|
||||
@ -280,7 +278,7 @@ impl Command for External {
|
||||
|
||||
let mut child = child.map_err(|err| {
|
||||
IoError::new_internal(
|
||||
err.kind(),
|
||||
err,
|
||||
"Could not spawn foreground child",
|
||||
nu_protocol::location!(),
|
||||
)
|
||||
@ -290,7 +288,7 @@ impl Command for External {
|
||||
if !thread_job.try_add_pid(child.pid()) {
|
||||
kill_by_pid(child.pid().into()).map_err(|err| {
|
||||
ShellError::Io(IoError::new_internal(
|
||||
err.kind(),
|
||||
err,
|
||||
"Could not spawn external stdin worker",
|
||||
nu_protocol::location!(),
|
||||
))
|
||||
@ -310,7 +308,7 @@ impl Command for External {
|
||||
})
|
||||
.map_err(|err| {
|
||||
IoError::new_with_additional_context(
|
||||
err.kind(),
|
||||
err,
|
||||
call.head,
|
||||
None,
|
||||
"Could not spawn external stdin worker",
|
||||
@ -498,7 +496,7 @@ fn write_pipeline_data(
|
||||
} else if let PipelineData::Value(Value::Binary { val, .. }, ..) = data {
|
||||
writer.write_all(&val).map_err(|err| {
|
||||
IoError::new_internal(
|
||||
err.kind(),
|
||||
err,
|
||||
"Could not write pipeline data",
|
||||
nu_protocol::location!(),
|
||||
)
|
||||
@ -518,7 +516,7 @@ fn write_pipeline_data(
|
||||
let bytes = value.coerce_into_binary()?;
|
||||
writer.write_all(&bytes).map_err(|err| {
|
||||
IoError::new_internal(
|
||||
err.kind(),
|
||||
err,
|
||||
"Could not write pipeline data",
|
||||
nu_protocol::location!(),
|
||||
)
|
||||
|
@ -518,7 +518,7 @@ fn pretty_hex_stream(stream: ByteStream, span: Span) -> ByteStream {
|
||||
(&mut reader)
|
||||
.take(cfg.width as u64)
|
||||
.read_to_end(&mut read_buf)
|
||||
.map_err(|err| IoError::new(err.kind(), span, None))?;
|
||||
.map_err(|err| IoError::new(err, span, None))?;
|
||||
|
||||
if !read_buf.is_empty() {
|
||||
nu_pretty_hex::hex_write(&mut write_buf, &read_buf, cfg, Some(true))
|
||||
|
@ -60,5 +60,5 @@ fn self_path_runtime() {
|
||||
fn self_path_repl() {
|
||||
let actual = nu!("const foo = path self; $foo");
|
||||
assert!(!actual.status.success());
|
||||
assert!(actual.err.contains("nu::shell::io::not_found"));
|
||||
assert!(actual.err.contains("nu::shell::io::file_not_found"));
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ use nu_test_support::playground::Playground;
|
||||
use rstest::rstest;
|
||||
#[cfg(not(windows))]
|
||||
use std::fs;
|
||||
#[cfg(windows)]
|
||||
use std::{fs::OpenOptions, os::windows::fs::OpenOptionsExt};
|
||||
|
||||
#[test]
|
||||
fn removes_a_file() {
|
||||
@ -562,3 +564,26 @@ fn rm_with_tilde() {
|
||||
assert!(!files_exist_at(&["~tilde"], dirs.test()));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn rm_already_in_use() {
|
||||
Playground::setup("rm_already_in_use", |dirs, sandbox| {
|
||||
sandbox.with_files(&[EmptyFile("i_will_be_used.txt")]);
|
||||
|
||||
let file_path = dirs.root().join("rm_already_in_use/i_will_be_used.txt");
|
||||
let _file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(false)
|
||||
.share_mode(0) // deny all sharing
|
||||
.open(file_path)
|
||||
.unwrap();
|
||||
|
||||
let outcome = nu!(
|
||||
cwd: dirs.root(),
|
||||
"rm rm_already_in_use/i_will_be_used.txt"
|
||||
);
|
||||
|
||||
assert!(outcome.err.contains("nu::shell::io::already_in_use"));
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user