mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 00:13:21 +01:00
run_external.rs: use pathdiff::diff_path to handle relative path (#13056)
# Description This pr is going to use `pathdiff::diff_path`, so we don't need to handle for relative path by ourselves. This is also the behavior before the rewritten of run_external.rs It's a follow up to https://github.com/nushell/nushell/pull/13028 # User-Facing Changes NaN # Tests + Formatting No need to add tests
This commit is contained in:
parent
e3a20e90b0
commit
83cf212e20
@ -8,6 +8,7 @@ use nu_protocol::{
|
||||
};
|
||||
use nu_system::ForegroundChild;
|
||||
use nu_utils::IgnoreCaseExt;
|
||||
use pathdiff::diff_paths;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
io::Write,
|
||||
@ -343,61 +344,54 @@ fn expand_glob(
|
||||
// We must use `nu_engine::glob_from` here, in order to ensure we get paths from the correct
|
||||
// dir
|
||||
let glob = NuGlob::Expand(arg.to_owned()).into_spanned(span);
|
||||
let Ok((_prefix, paths)) = nu_engine::glob_from(&glob, cwd, span, None) else {
|
||||
// If an error occurred, return the original input
|
||||
return Ok(vec![arg.into()]);
|
||||
};
|
||||
if let Ok((prefix, matches)) = nu_engine::glob_from(&glob, cwd, span, None) {
|
||||
let mut result = vec![];
|
||||
|
||||
// If the first component of the original `arg` string path was '.', that should be preserved
|
||||
let relative_to_dot = Path::new(arg).starts_with(".");
|
||||
|
||||
let paths = paths
|
||||
// Skip over glob failures. These are usually just inaccessible paths.
|
||||
.flat_map(|path_result| match path_result {
|
||||
Ok(path) => Some(path),
|
||||
Err(err) => {
|
||||
// But internally log them just in case we need to debug this.
|
||||
log::warn!("Error in run_external::expand_glob(): {}", err);
|
||||
None
|
||||
for m in matches {
|
||||
if nu_utils::ctrl_c::was_pressed(interrupt) {
|
||||
return Err(ShellError::InterruptedByUser { span: Some(span) });
|
||||
}
|
||||
})
|
||||
// Make the paths relative to the cwd
|
||||
.map(|path| {
|
||||
path.strip_prefix(cwd)
|
||||
.map(|path| path.to_owned())
|
||||
.unwrap_or(path)
|
||||
})
|
||||
// Add './' to relative paths if the original pattern had it
|
||||
.map(|path| {
|
||||
if relative_to_dot && path.is_relative() {
|
||||
Path::new(".").join(path)
|
||||
if let Ok(arg) = m {
|
||||
let arg = resolve_globbed_path_to_cwd_relative(arg, prefix.as_ref(), cwd);
|
||||
result.push(arg.to_string_lossy().to_string());
|
||||
} else {
|
||||
path
|
||||
result.push(arg.into());
|
||||
}
|
||||
})
|
||||
// Convert the paths returned to UTF-8 strings.
|
||||
//
|
||||
// FIXME: this fails to return the correct results for non-UTF-8 paths, but we don't support
|
||||
// those in Nushell yet.
|
||||
.map(|path| path.to_string_lossy().into_owned())
|
||||
// Abandon if ctrl-c is pressed
|
||||
.map(|path| {
|
||||
if !nu_utils::ctrl_c::was_pressed(interrupt) {
|
||||
Ok(path)
|
||||
} else {
|
||||
Err(ShellError::InterruptedByUser { span: Some(span) })
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<String>, ShellError>>()?;
|
||||
}
|
||||
|
||||
if !paths.is_empty() {
|
||||
Ok(paths)
|
||||
// FIXME: do we want to special-case this further? We might accidentally expand when they don't
|
||||
// intend to
|
||||
if result.is_empty() {
|
||||
result.push(arg.into());
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
// If we failed to match, return the original input
|
||||
Ok(vec![arg.into()])
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_globbed_path_to_cwd_relative(
|
||||
path: PathBuf,
|
||||
prefix: Option<&PathBuf>,
|
||||
cwd: &Path,
|
||||
) -> PathBuf {
|
||||
if let Some(prefix) = prefix {
|
||||
if let Ok(remainder) = path.strip_prefix(prefix) {
|
||||
let new_prefix = if let Some(pfx) = diff_paths(prefix, cwd) {
|
||||
pfx
|
||||
} else {
|
||||
prefix.to_path_buf()
|
||||
};
|
||||
new_prefix.join(remainder)
|
||||
} else {
|
||||
path
|
||||
}
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms `--option="value"` into `--option=value`. `value` can be quoted
|
||||
/// with double quotes, single quotes, or backticks. Only removes the outermost
|
||||
/// pair of quotes after the equal sign.
|
||||
@ -716,10 +710,6 @@ mod test {
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = expand_glob("./*.txt", cwd, Span::unknown(), &None).unwrap();
|
||||
let expected = vec![
|
||||
Path::new(".").join("a.txt").to_string_lossy().into_owned(),
|
||||
Path::new(".").join("b.txt").to_string_lossy().into_owned(),
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = expand_glob("'*.txt'", cwd, Span::unknown(), &None).unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user