mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 08:26:22 +02:00
check signals in nu-glob
and ls
(#15140)
Fixes #10144 # User-Facing Changes Long running glob expansions and `ls` runs (e.g. `ls /**/*`) can now be interrupted with ctrl-c.
This commit is contained in:
@ -118,7 +118,7 @@ impl Command for Du {
|
||||
min_size,
|
||||
};
|
||||
Ok(
|
||||
du_for_one_pattern(args, ¤t_dir, tag, engine_state.signals())?
|
||||
du_for_one_pattern(args, ¤t_dir, tag, engine_state.signals().clone())?
|
||||
.into_pipeline_data(tag, engine_state.signals().clone()),
|
||||
)
|
||||
}
|
||||
@ -137,7 +137,7 @@ impl Command for Du {
|
||||
args,
|
||||
¤t_dir,
|
||||
tag,
|
||||
engine_state.signals(),
|
||||
engine_state.signals().clone(),
|
||||
)?)
|
||||
}
|
||||
|
||||
@ -163,9 +163,8 @@ fn du_for_one_pattern(
|
||||
args: DuArgs,
|
||||
current_dir: &Path,
|
||||
span: Span,
|
||||
signals: &Signals,
|
||||
signals: Signals,
|
||||
) -> Result<impl Iterator<Item = Value> + Send, ShellError> {
|
||||
let signals_clone = signals.clone();
|
||||
let exclude = args.exclude.map_or(Ok(None), move |x| {
|
||||
Pattern::new(x.item.as_ref())
|
||||
.map(Some)
|
||||
@ -176,7 +175,8 @@ fn du_for_one_pattern(
|
||||
})?;
|
||||
|
||||
let paths = match args.path {
|
||||
Some(p) => nu_engine::glob_from(&p, current_dir, span, None),
|
||||
Some(p) => nu_engine::glob_from(&p, current_dir, span, None, signals.clone()),
|
||||
|
||||
// The * pattern should never fail.
|
||||
None => nu_engine::glob_from(
|
||||
&Spanned {
|
||||
@ -186,6 +186,7 @@ fn du_for_one_pattern(
|
||||
current_dir,
|
||||
span,
|
||||
None,
|
||||
signals.clone(),
|
||||
),
|
||||
}
|
||||
.map(|f| f.1)?;
|
||||
@ -206,7 +207,7 @@ fn du_for_one_pattern(
|
||||
Ok(paths.filter_map(move |p| match p {
|
||||
Ok(a) => {
|
||||
if a.is_dir() {
|
||||
match DirInfo::new(a, ¶ms, max_depth, span, &signals_clone) {
|
||||
match DirInfo::new(a, ¶ms, max_depth, span, &signals) {
|
||||
Ok(v) => Some(Value::from(v)),
|
||||
Err(_) => None,
|
||||
}
|
||||
|
@ -285,7 +285,10 @@ fn ls_for_one_pattern(
|
||||
nu_path::expand_path_with(pat.item.as_ref(), &cwd, pat.item.is_expand());
|
||||
// Avoid checking and pushing "*" to the path when directory (do not show contents) flag is true
|
||||
if !directory && tmp_expanded.is_dir() {
|
||||
if read_dir(tmp_expanded, p_tag, use_threads)?.next().is_none() {
|
||||
if read_dir(tmp_expanded, p_tag, use_threads, signals.clone())?
|
||||
.next()
|
||||
.is_none()
|
||||
{
|
||||
return Ok(Value::test_nothing().into_pipeline_data());
|
||||
}
|
||||
just_read_dir = !(pat.item.is_expand() && nu_glob::is_glob(pat.item.as_ref()));
|
||||
@ -304,7 +307,10 @@ fn ls_for_one_pattern(
|
||||
// Avoid pushing "*" to the default path when directory (do not show contents) flag is true
|
||||
if directory {
|
||||
(NuGlob::Expand(".".to_string()), false)
|
||||
} else if read_dir(cwd.clone(), p_tag, use_threads)?.next().is_none() {
|
||||
} else if read_dir(cwd.clone(), p_tag, use_threads, signals.clone())?
|
||||
.next()
|
||||
.is_none()
|
||||
{
|
||||
return Ok(Value::test_nothing().into_pipeline_data());
|
||||
} else {
|
||||
(NuGlob::Expand("*".to_string()), false)
|
||||
@ -317,7 +323,7 @@ fn ls_for_one_pattern(
|
||||
let path = pattern_arg.into_spanned(p_tag);
|
||||
let (prefix, paths) = if just_read_dir {
|
||||
let expanded = nu_path::expand_path_with(path.item.as_ref(), &cwd, path.item.is_expand());
|
||||
let paths = read_dir(expanded.clone(), p_tag, use_threads)?;
|
||||
let paths = read_dir(expanded.clone(), p_tag, use_threads, signals.clone())?;
|
||||
// just need to read the directory, so prefix is path itself.
|
||||
(Some(expanded), paths)
|
||||
} else {
|
||||
@ -330,11 +336,13 @@ fn ls_for_one_pattern(
|
||||
};
|
||||
Some(glob_options)
|
||||
};
|
||||
glob_from(&path, &cwd, call_span, glob_options)?
|
||||
glob_from(&path, &cwd, call_span, glob_options, signals.clone())?
|
||||
};
|
||||
|
||||
let mut paths_peek = paths.peekable();
|
||||
if paths_peek.peek().is_none() {
|
||||
let no_matches = paths_peek.peek().is_none();
|
||||
signals.check(call_span)?;
|
||||
if no_matches {
|
||||
return Err(ShellError::GenericError {
|
||||
error: format!("No matches found for {:?}", path.item),
|
||||
msg: "Pattern, file or folder not found".into(),
|
||||
@ -959,17 +967,21 @@ fn read_dir(
|
||||
f: PathBuf,
|
||||
span: Span,
|
||||
use_threads: bool,
|
||||
signals: Signals,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<PathBuf, ShellError>> + Send>, ShellError> {
|
||||
let signals_clone = signals.clone();
|
||||
let items = f
|
||||
.read_dir()
|
||||
.map_err(|err| IoError::new(err.kind(), 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(ShellError::from)
|
||||
});
|
||||
if !use_threads {
|
||||
let mut collected = items.collect::<Vec<_>>();
|
||||
signals.check(span)?;
|
||||
collected.sort_by(|a, b| match (a, b) {
|
||||
(Ok(a), Ok(b)) => a.cmp(b),
|
||||
(Ok(_), Err(_)) => Ordering::Greater,
|
||||
|
@ -95,16 +95,17 @@ impl Command for Open {
|
||||
let arg_span = path.span;
|
||||
// let path_no_whitespace = &path.item.trim_end_matches(|x| matches!(x, '\x09'..='\x0d'));
|
||||
|
||||
for path in nu_engine::glob_from(&path, &cwd, call_span, None)
|
||||
.map_err(|err| match err {
|
||||
ShellError::Io(mut err) => {
|
||||
err.kind = err.kind.not_found_as(NotFound::File);
|
||||
err.span = arg_span;
|
||||
err.into()
|
||||
}
|
||||
_ => err,
|
||||
})?
|
||||
.1
|
||||
for path in
|
||||
nu_engine::glob_from(&path, &cwd, call_span, None, engine_state.signals().clone())
|
||||
.map_err(|err| match err {
|
||||
ShellError::Io(mut err) => {
|
||||
err.kind = err.kind.not_found_as(NotFound::File);
|
||||
err.span = arg_span;
|
||||
err.into()
|
||||
}
|
||||
_ => err,
|
||||
})?
|
||||
.1
|
||||
{
|
||||
let path = path?;
|
||||
let path = Path::new(&path);
|
||||
|
@ -260,6 +260,7 @@ fn rm(
|
||||
require_literal_leading_dot: true,
|
||||
..Default::default()
|
||||
}),
|
||||
engine_state.signals().clone(),
|
||||
) {
|
||||
Ok(files) => {
|
||||
for file in files.1 {
|
||||
|
@ -193,7 +193,7 @@ impl Command for UCp {
|
||||
for mut p in paths {
|
||||
p.item = p.item.strip_ansi_string_unlikely();
|
||||
let exp_files: Vec<Result<PathBuf, ShellError>> =
|
||||
nu_engine::glob_from(&p, &cwd, call.head, None)
|
||||
nu_engine::glob_from(&p, &cwd, call.head, None, engine_state.signals().clone())
|
||||
.map(|f| f.1)?
|
||||
.collect();
|
||||
if exp_files.is_empty() {
|
||||
|
@ -134,7 +134,7 @@ impl Command for UMv {
|
||||
for mut p in paths {
|
||||
p.item = p.item.strip_ansi_string_unlikely();
|
||||
let exp_files: Vec<Result<PathBuf, ShellError>> =
|
||||
nu_engine::glob_from(&p, &cwd, call.head, None)
|
||||
nu_engine::glob_from(&p, &cwd, call.head, None, engine_state.signals().clone())
|
||||
.map(|f| f.1)?
|
||||
.collect();
|
||||
if exp_files.is_empty() {
|
||||
|
@ -158,14 +158,17 @@ impl Command for UTouch {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut expanded_globs = glob(&file_path.to_string_lossy())
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Failed to process file path: {}",
|
||||
&file_path.to_string_lossy()
|
||||
)
|
||||
})
|
||||
.peekable();
|
||||
let mut expanded_globs = glob(
|
||||
&file_path.to_string_lossy(),
|
||||
Some(engine_state.signals().clone()),
|
||||
)
|
||||
.unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Failed to process file path: {}",
|
||||
&file_path.to_string_lossy()
|
||||
)
|
||||
})
|
||||
.peekable();
|
||||
|
||||
if expanded_globs.peek().is_none() {
|
||||
let file_name = file_path.file_name().unwrap_or_else(|| {
|
||||
|
Reference in New Issue
Block a user