mirror of
https://github.com/nushell/nushell.git
synced 2025-06-08 11:06:55 +02:00
fix(glob): Fix drive-letter glob expansion on Windows (#15871)
# Description This PR fixes drive-letter glob expansion on Windows. It adds a bit of pre-processing to play better with the wax crate. This change is following suggestions from this thread on the wax repo: https://github.com/olson-sean-k/wax/issues/34 fixes #15707 #7125
This commit is contained in:
parent
74e0e4f092
commit
ed7b2615c1
@ -168,6 +168,10 @@ impl Command for Glob {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// paths starting with drive letters must be escaped on Windows
|
||||||
|
#[cfg(windows)]
|
||||||
|
let glob_pattern = patch_windows_glob_pattern(glob_pattern, glob_span)?;
|
||||||
|
|
||||||
if glob_pattern.is_empty() {
|
if glob_pattern.is_empty() {
|
||||||
return Err(ShellError::GenericError {
|
return Err(ShellError::GenericError {
|
||||||
error: "glob pattern must not be empty".into(),
|
error: "glob pattern must not be empty".into(),
|
||||||
@ -280,6 +284,26 @@ impl Command for Glob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn patch_windows_glob_pattern(glob_pattern: String, glob_span: Span) -> Result<String, ShellError> {
|
||||||
|
let mut chars = glob_pattern.chars();
|
||||||
|
match (chars.next(), chars.next(), chars.next()) {
|
||||||
|
(Some(drive), Some(':'), Some('/' | '\\')) if drive.is_ascii_alphabetic() => {
|
||||||
|
Ok(format!("{drive}\\:/{}", chars.as_str()))
|
||||||
|
}
|
||||||
|
(Some(drive), Some(':'), Some(_)) if drive.is_ascii_alphabetic() => {
|
||||||
|
Err(ShellError::GenericError {
|
||||||
|
error: "invalid Windows path format".into(),
|
||||||
|
msg: "Windows paths with drive letters must include a path separator (/) after the colon".into(),
|
||||||
|
span: Some(glob_span),
|
||||||
|
help: Some("use format like 'C:/' instead of 'C:'".into()),
|
||||||
|
inner: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Ok(glob_pattern),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn convert_patterns(columns: &[Value]) -> Result<Vec<String>, ShellError> {
|
fn convert_patterns(columns: &[Value]) -> Result<Vec<String>, ShellError> {
|
||||||
let res = columns
|
let res = columns
|
||||||
.iter()
|
.iter()
|
||||||
@ -325,3 +349,53 @@ fn glob_to_value(
|
|||||||
|
|
||||||
ListStream::new(result, span, signals.clone())
|
ListStream::new(result, span, signals.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[cfg(test)]
|
||||||
|
mod windows_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn glob_pattern_with_drive_letter() {
|
||||||
|
let pattern = "D:/*.mp4".to_string();
|
||||||
|
let result = patch_windows_glob_pattern(pattern, Span::test_data()).unwrap();
|
||||||
|
assert!(WaxGlob::new(&result).is_ok());
|
||||||
|
|
||||||
|
let pattern = "Z:/**/*.md".to_string();
|
||||||
|
let result = patch_windows_glob_pattern(pattern, Span::test_data()).unwrap();
|
||||||
|
assert!(WaxGlob::new(&result).is_ok());
|
||||||
|
|
||||||
|
let pattern = "C:/nested/**/escaped/path/<[_a-zA-Z\\-]>.md".to_string();
|
||||||
|
let result = patch_windows_glob_pattern(pattern, Span::test_data()).unwrap();
|
||||||
|
assert!(dbg!(WaxGlob::new(&result)).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn glob_pattern_without_drive_letter() {
|
||||||
|
let pattern = "/usr/bin/*.sh".to_string();
|
||||||
|
let result = patch_windows_glob_pattern(pattern.clone(), Span::test_data()).unwrap();
|
||||||
|
assert_eq!(result, pattern);
|
||||||
|
assert!(WaxGlob::new(&result).is_ok());
|
||||||
|
|
||||||
|
let pattern = "a".to_string();
|
||||||
|
let result = patch_windows_glob_pattern(pattern.clone(), Span::test_data()).unwrap();
|
||||||
|
assert_eq!(result, pattern);
|
||||||
|
assert!(WaxGlob::new(&result).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_path_format() {
|
||||||
|
let invalid = "C:lol".to_string();
|
||||||
|
let result = patch_windows_glob_pattern(invalid, Span::test_data());
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unpatched_patterns() {
|
||||||
|
let unpatched = "C:/Users/*.txt".to_string();
|
||||||
|
assert!(WaxGlob::new(&unpatched).is_err());
|
||||||
|
|
||||||
|
let patched = patch_windows_glob_pattern(unpatched, Span::test_data()).unwrap();
|
||||||
|
assert!(WaxGlob::new(&patched).is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user