forked from extern/nushell
Convert more ShellError variants to named fields (#11173)
# Description Convert these ShellError variants to named fields: * CreateNotPossible * MoveNotPossibleSingle * DirectoryNotFoundCustom * DirectoryNotFound * NotADirectory * OutOfMemoryError * PermissionDeniedError * IOErrorSpanned * IOError * IOInterrupted Also place the `span` field of `DirectoryNotFound` last to match other errors. Part of #10700 (almost half done!) # User-Facing Changes None # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` # After Submitting N/A
This commit is contained in:
@ -83,10 +83,10 @@ impl Command for Cd {
|
||||
let path = match nu_path::canonicalize_with(path.clone(), &cwd) {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
return Err(ShellError::DirectoryNotFound(
|
||||
v.span,
|
||||
path.to_string_lossy().to_string(),
|
||||
));
|
||||
return Err(ShellError::DirectoryNotFound {
|
||||
dir: path.to_string_lossy().to_string(),
|
||||
span: v.span,
|
||||
});
|
||||
}
|
||||
};
|
||||
(path.to_string_lossy().to_string(), v.span)
|
||||
@ -100,17 +100,17 @@ impl Command for Cd {
|
||||
let path = match nu_path::canonicalize_with(path_no_whitespace, &cwd) {
|
||||
Ok(p) => {
|
||||
if !p.is_dir() {
|
||||
return Err(ShellError::NotADirectory(v.span));
|
||||
return Err(ShellError::NotADirectory { span: v.span });
|
||||
};
|
||||
p
|
||||
}
|
||||
|
||||
// if canonicalize failed, let's check to see if it's abbreviated
|
||||
Err(_) => {
|
||||
return Err(ShellError::DirectoryNotFound(
|
||||
v.span,
|
||||
path_no_whitespace.to_string(),
|
||||
));
|
||||
return Err(ShellError::DirectoryNotFound {
|
||||
dir: path_no_whitespace.to_string(),
|
||||
span: v.span,
|
||||
});
|
||||
}
|
||||
};
|
||||
(path.to_string_lossy().to_string(), v.span)
|
||||
@ -135,9 +135,9 @@ impl Command for Cd {
|
||||
stack.add_env_var("PWD".into(), path_value);
|
||||
Ok(PipelineData::empty())
|
||||
}
|
||||
PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError(format!(
|
||||
"Cannot change directory to {path}: {reason}"
|
||||
))),
|
||||
PermissionResult::PermissionDenied(reason) => Err(ShellError::IOError {
|
||||
msg: format!("Cannot change directory to {path}: {reason}"),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,10 +88,10 @@ impl Command for Cp {
|
||||
let path_last_char = destination.as_os_str().to_string_lossy().chars().last();
|
||||
let is_directory = path_last_char == Some('/') || path_last_char == Some('\\');
|
||||
if is_directory && !destination.exists() {
|
||||
return Err(ShellError::DirectoryNotFound(
|
||||
dst.span,
|
||||
destination.to_string_lossy().to_string(),
|
||||
));
|
||||
return Err(ShellError::DirectoryNotFound {
|
||||
dir: destination.to_string_lossy().to_string(),
|
||||
span: dst.span,
|
||||
});
|
||||
}
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
let span = call.head;
|
||||
@ -577,18 +577,36 @@ fn convert_io_error(error: std::io::Error, src: PathBuf, dst: PathBuf, span: Spa
|
||||
ErrorKind::PermissionDenied => match std::fs::metadata(&dst) {
|
||||
Ok(meta) => {
|
||||
if meta.permissions().readonly() {
|
||||
ShellError::PermissionDeniedError(message_dst, span)
|
||||
ShellError::PermissionDeniedError {
|
||||
msg: message_dst,
|
||||
span,
|
||||
}
|
||||
} else {
|
||||
ShellError::PermissionDeniedError(message_src, span)
|
||||
ShellError::PermissionDeniedError {
|
||||
msg: message_src,
|
||||
span,
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => ShellError::PermissionDeniedError(message_dst, span),
|
||||
Err(_) => ShellError::PermissionDeniedError {
|
||||
msg: message_dst,
|
||||
span,
|
||||
},
|
||||
},
|
||||
ErrorKind::Interrupted => ShellError::IOInterrupted {
|
||||
msg: message_src,
|
||||
span,
|
||||
},
|
||||
ErrorKind::OutOfMemory => ShellError::OutOfMemoryError {
|
||||
msg: message_src,
|
||||
span,
|
||||
},
|
||||
ErrorKind::Interrupted => ShellError::IOInterrupted(message_src, span),
|
||||
ErrorKind::OutOfMemory => ShellError::OutOfMemoryError(message_src, span),
|
||||
// TODO: handle ExecutableFileBusy etc. when io_error_more is stabilized
|
||||
// https://github.com/rust-lang/rust/issues/86442
|
||||
_ => ShellError::IOErrorSpanned(message_src, span),
|
||||
_ => ShellError::IOErrorSpanned {
|
||||
msg: message_src,
|
||||
span,
|
||||
},
|
||||
};
|
||||
|
||||
Value::error(shell_error, span)
|
||||
|
@ -69,12 +69,13 @@ impl Command for Mkdir {
|
||||
let dir_res = std::fs::create_dir_all(&dir);
|
||||
|
||||
if let Err(reason) = dir_res {
|
||||
return Err(ShellError::CreateNotPossible(
|
||||
format!("failed to create directory: {reason}"),
|
||||
call.positional_nth(i)
|
||||
return Err(ShellError::CreateNotPossible {
|
||||
msg: format!("failed to create directory: {reason}"),
|
||||
span: call
|
||||
.positional_nth(i)
|
||||
.expect("already checked through directories")
|
||||
.span,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
if is_verbose {
|
||||
|
@ -110,10 +110,14 @@ impl Command for Mktemp {
|
||||
};
|
||||
|
||||
let res = match uu_mktemp::mktemp(&options) {
|
||||
Ok(res) => res
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.map_err(|e| ShellError::IOErrorSpanned(e.to_string_lossy().to_string(), span))?,
|
||||
Ok(res) => {
|
||||
res.into_os_string()
|
||||
.into_string()
|
||||
.map_err(|e| ShellError::IOErrorSpanned {
|
||||
msg: e.to_string_lossy().to_string(),
|
||||
span,
|
||||
})?
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(ShellError::GenericError(
|
||||
format!("{}", e),
|
||||
|
@ -260,10 +260,10 @@ fn move_file(
|
||||
};
|
||||
|
||||
if !destination_dir_exists {
|
||||
return Err(ShellError::DirectoryNotFound(
|
||||
to_span,
|
||||
to.to_string_lossy().to_string(),
|
||||
));
|
||||
return Err(ShellError::DirectoryNotFound {
|
||||
dir: to.to_string_lossy().to_string(),
|
||||
span: to_span,
|
||||
});
|
||||
}
|
||||
|
||||
// This can happen when changing case on a case-insensitive filesystem (ex: changing foo to Foo on Windows)
|
||||
@ -275,10 +275,10 @@ fn move_file(
|
||||
let from_file_name = match from.file_name() {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
return Err(ShellError::DirectoryNotFound(
|
||||
to_span,
|
||||
from.to_string_lossy().to_string(),
|
||||
))
|
||||
return Err(ShellError::DirectoryNotFound {
|
||||
dir: from.to_string_lossy().to_string(),
|
||||
span: to_span,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -105,7 +105,7 @@ impl Command for Open {
|
||||
|
||||
for path in nu_engine::glob_from(&path, &cwd, call_span, None)
|
||||
.map_err(|err| match err {
|
||||
ShellError::DirectoryNotFound(span, _) => ShellError::FileNotFound { span },
|
||||
ShellError::DirectoryNotFound { span, .. } => ShellError::FileNotFound { span },
|
||||
_ => err,
|
||||
})?
|
||||
.1
|
||||
|
@ -162,9 +162,13 @@ impl Command for Save {
|
||||
)?;
|
||||
for val in ls {
|
||||
file.write_all(&value_to_bytes(val)?)
|
||||
.map_err(|err| ShellError::IOError(err.to_string()))?;
|
||||
.map_err(|err| ShellError::IOError {
|
||||
msg: err.to_string(),
|
||||
})?;
|
||||
file.write_all("\n".as_bytes())
|
||||
.map_err(|err| ShellError::IOError(err.to_string()))?;
|
||||
.map_err(|err| ShellError::IOError {
|
||||
msg: err.to_string(),
|
||||
})?;
|
||||
}
|
||||
file.flush()?;
|
||||
|
||||
@ -184,8 +188,9 @@ impl Command for Save {
|
||||
force,
|
||||
)?;
|
||||
|
||||
file.write_all(&bytes)
|
||||
.map_err(|err| ShellError::IOError(err.to_string()))?;
|
||||
file.write_all(&bytes).map_err(|err| ShellError::IOError {
|
||||
msg: err.to_string(),
|
||||
})?;
|
||||
|
||||
file.flush()?;
|
||||
|
||||
@ -453,7 +458,9 @@ fn stream_to_file(
|
||||
|
||||
if let Err(err) = writer.write(&buf) {
|
||||
*process_failed_p = true;
|
||||
return Err(ShellError::IOError(err.to_string()));
|
||||
return Err(ShellError::IOError {
|
||||
msg: err.to_string(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -136,12 +136,13 @@ impl Command for Touch {
|
||||
}
|
||||
|
||||
if let Err(err) = OpenOptions::new().write(true).create(true).open(&item) {
|
||||
return Err(ShellError::CreateNotPossible(
|
||||
format!("Failed to create file: {err}"),
|
||||
call.positional_nth(index)
|
||||
return Err(ShellError::CreateNotPossible {
|
||||
msg: format!("Failed to create file: {err}"),
|
||||
span: call
|
||||
.positional_nth(index)
|
||||
.expect("already checked positional")
|
||||
.span,
|
||||
));
|
||||
});
|
||||
};
|
||||
|
||||
if change_mtime {
|
||||
|
@ -83,10 +83,10 @@ impl Command for Watch {
|
||||
let path = match nu_path::canonicalize_with(path_no_whitespace, cwd) {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
return Err(ShellError::DirectoryNotFound(
|
||||
path_arg.span,
|
||||
path_no_whitespace.to_string(),
|
||||
))
|
||||
return Err(ShellError::DirectoryNotFound {
|
||||
dir: path_no_whitespace.to_string(),
|
||||
span: path_arg.span,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
@ -153,15 +153,15 @@ impl Command for Watch {
|
||||
let mut debouncer = match new_debouncer(debounce_duration, None, tx) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
return Err(ShellError::IOError(format!(
|
||||
"Failed to create watcher: {e}"
|
||||
)))
|
||||
return Err(ShellError::IOError {
|
||||
msg: format!("Failed to create watcher: {e}"),
|
||||
})
|
||||
}
|
||||
};
|
||||
if let Err(e) = debouncer.watcher().watch(&path, recursive_mode) {
|
||||
return Err(ShellError::IOError(format!(
|
||||
"Failed to create watcher: {e}"
|
||||
)));
|
||||
return Err(ShellError::IOError {
|
||||
msg: format!("Failed to create watcher: {e}"),
|
||||
});
|
||||
}
|
||||
// need to cache to make sure that rename event works.
|
||||
debouncer.cache().add_root(&path, recursive_mode);
|
||||
@ -275,14 +275,14 @@ impl Command for Watch {
|
||||
}
|
||||
}
|
||||
Ok(Err(_)) => {
|
||||
return Err(ShellError::IOError(
|
||||
"Unexpected errors when receiving events".into(),
|
||||
))
|
||||
return Err(ShellError::IOError {
|
||||
msg: "Unexpected errors when receiving events".into(),
|
||||
})
|
||||
}
|
||||
Err(RecvTimeoutError::Disconnected) => {
|
||||
return Err(ShellError::IOError(
|
||||
"Unexpected disconnect from file watcher".into(),
|
||||
));
|
||||
return Err(ShellError::IOError {
|
||||
msg: "Unexpected disconnect from file watcher".into(),
|
||||
});
|
||||
}
|
||||
Err(RecvTimeoutError::Timeout) => {}
|
||||
}
|
||||
|
@ -209,9 +209,9 @@ pub fn send_request(
|
||||
}
|
||||
Value::List { vals, .. } if body_type == BodyType::Form => {
|
||||
if vals.len() % 2 != 0 {
|
||||
return Err(ShellErrorOrRequestError::ShellError(ShellError::IOError(
|
||||
"unsupported body input".into(),
|
||||
)));
|
||||
return Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
|
||||
msg: "unsupported body input".into(),
|
||||
}));
|
||||
}
|
||||
|
||||
let data = vals
|
||||
@ -233,9 +233,9 @@ pub fn send_request(
|
||||
let data = value_to_json_value(&body)?;
|
||||
send_cancellable_request(&request_url, Box::new(|| request.send_json(data)), ctrl_c)
|
||||
}
|
||||
_ => Err(ShellErrorOrRequestError::ShellError(ShellError::IOError(
|
||||
"unsupported body input".into(),
|
||||
))),
|
||||
_ => Err(ShellErrorOrRequestError::ShellError(ShellError::IOError {
|
||||
msg: "unsupported body input".into(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,13 @@ fn exists(path: &Path, span: Span, args: &Arguments) -> Value {
|
||||
match path.try_exists() {
|
||||
Ok(exists) => exists,
|
||||
Err(err) => {
|
||||
return Value::error(ShellError::IOErrorSpanned(err.to_string(), span), span)
|
||||
return Value::error(
|
||||
ShellError::IOErrorSpanned {
|
||||
msg: err.to_string(),
|
||||
span,
|
||||
},
|
||||
span,
|
||||
)
|
||||
}
|
||||
},
|
||||
span,
|
||||
|
@ -36,7 +36,10 @@ impl Command for Clear {
|
||||
CommandSys::new("cmd")
|
||||
.args(["/C", "cls"])
|
||||
.status()
|
||||
.map_err(|e| ShellError::IOErrorSpanned(e.to_string(), span))?;
|
||||
.map_err(|e| ShellError::IOErrorSpanned {
|
||||
msg: e.to_string(),
|
||||
span,
|
||||
})?;
|
||||
} else if cfg!(unix) {
|
||||
let mut cmd = CommandSys::new("/bin/sh");
|
||||
|
||||
@ -46,7 +49,10 @@ impl Command for Clear {
|
||||
|
||||
cmd.args(["-c", "clear"])
|
||||
.status()
|
||||
.map_err(|e| ShellError::IOErrorSpanned(e.to_string(), span))?;
|
||||
.map_err(|e| ShellError::IOErrorSpanned {
|
||||
msg: e.to_string(),
|
||||
span,
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(Value::nothing(span).into_pipeline_data())
|
||||
|
@ -110,7 +110,9 @@ impl Command for Input {
|
||||
{
|
||||
if k.modifiers == KeyModifiers::CONTROL && c == 'c' {
|
||||
crossterm::terminal::disable_raw_mode()?;
|
||||
return Err(ShellError::IOError("SIGINT".to_string()));
|
||||
return Err(ShellError::IOError {
|
||||
msg: "SIGINT".to_string(),
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -196,7 +196,9 @@ impl Command for InputList {
|
||||
.items(&options)
|
||||
.report(false)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.map_err(|err| ShellError::IOError(format!("{}: {}", INTERACT_ERROR, err)))?,
|
||||
.map_err(|err| ShellError::IOError {
|
||||
msg: format!("{}: {}", INTERACT_ERROR, err),
|
||||
})?,
|
||||
)
|
||||
} else if call.has_flag("fuzzy") {
|
||||
let fuzzy_select = FuzzySelect::new(); //::with_theme(&theme);
|
||||
@ -211,7 +213,9 @@ impl Command for InputList {
|
||||
.default(0)
|
||||
.report(false)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.map_err(|err| ShellError::IOError(format!("{}: {}", INTERACT_ERROR, err)))?,
|
||||
.map_err(|err| ShellError::IOError {
|
||||
msg: format!("{}: {}", INTERACT_ERROR, err),
|
||||
})?,
|
||||
)
|
||||
} else {
|
||||
let select = Select::new(); //::with_theme(&theme);
|
||||
@ -225,7 +229,9 @@ impl Command for InputList {
|
||||
.default(0)
|
||||
.report(false)
|
||||
.interact_on_opt(&Term::stderr())
|
||||
.map_err(|err| ShellError::IOError(format!("{}: {}", INTERACT_ERROR, err)))?,
|
||||
.map_err(|err| ShellError::IOError {
|
||||
msg: format!("{}: {}", INTERACT_ERROR, err),
|
||||
})?,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -301,7 +301,9 @@ fn heuristic_parse_file(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::IOError("Can not read input".to_string()))
|
||||
Err(ShellError::IOError {
|
||||
msg: "Can not read input".to_string(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::NotFound { span: call.head })
|
||||
@ -402,7 +404,9 @@ fn parse_file_script(
|
||||
call.head,
|
||||
)
|
||||
} else {
|
||||
Err(ShellError::IOError("Can not read path".to_string()))
|
||||
Err(ShellError::IOError {
|
||||
msg: "Can not read path".to_string(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::NotFound { span: call.head })
|
||||
@ -425,7 +429,9 @@ fn parse_file_module(
|
||||
if let Ok(contents) = std::fs::read(path) {
|
||||
parse_module(working_set, Some(filename), &contents, is_debug, call.head)
|
||||
} else {
|
||||
Err(ShellError::IOError("Can not read path".to_string()))
|
||||
Err(ShellError::IOError {
|
||||
msg: "Can not read path".to_string(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Err(ShellError::NotFound { span: call.head })
|
||||
|
Reference in New Issue
Block a user