Implement ctrl+c for the du command (#1901)

* Implement ctrl+c for the du command

* Ignore the "too many arguments" Clippy warning
This commit is contained in:
Joseph T. Lyons 2020-05-27 00:52:20 -04:00 committed by GitHub
parent fa812849b8
commit 49b0592e3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 8 deletions

View File

@ -7,6 +7,7 @@ use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
use std::path::PathBuf;
use std::sync::atomic::Ordering;
const NAME: &str = "du";
const GLOB_PARAMS: MatchOptions = MatchOptions {
@ -92,6 +93,7 @@ fn du(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, She
let registry = registry.clone();
let tag = args.call_info.name_tag.clone();
let ctrl_c = args.ctrl_c.clone();
let ctrl_c_copy = ctrl_c.clone();
let stream = async_stream! {
let (args, mut input): (DuArgs, _) = args.process(&registry).await?;
@ -136,13 +138,14 @@ fn du(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, She
all,
};
let mut inp = futures::stream::iter(paths).interruptible(ctrl_c);
let mut inp = futures::stream::iter(paths).interruptible(ctrl_c.clone());
while let Some(path) = inp.next().await {
match path {
Ok(p) => {
if p.is_dir() {
yield Ok(ReturnSuccess::Value(
DirInfo::new(p, &params, max_depth).into(),
DirInfo::new(p, &params, max_depth, ctrl_c.clone()).into(),
))
} else {
for v in FileInfo::new(p, deref, tag.clone()).into_iter() {
@ -155,7 +158,7 @@ fn du(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, She
}
};
Ok(stream.to_output_stream())
Ok(stream.interruptible(ctrl_c_copy).to_output_stream())
}
pub struct DirBuilder {
@ -227,7 +230,12 @@ impl FileInfo {
}
impl DirInfo {
pub fn new(path: impl Into<PathBuf>, params: &DirBuilder, depth: Option<u64>) -> Self {
pub fn new(
path: impl Into<PathBuf>,
params: &DirBuilder,
depth: Option<u64>,
ctrl_c: Arc<AtomicBool>,
) -> Self {
let path = path.into();
let mut s = Self {
@ -243,9 +251,15 @@ impl DirInfo {
match std::fs::read_dir(&s.path) {
Ok(d) => {
for f in d {
if ctrl_c.load(Ordering::SeqCst) {
break;
}
match f {
Ok(i) => match i.file_type() {
Ok(t) if t.is_dir() => s = s.add_dir(i.path(), depth, &params),
Ok(t) if t.is_dir() => {
s = s.add_dir(i.path(), depth, &params, ctrl_c.clone())
}
Ok(_t) => s = s.add_file(i.path(), &params),
Err(e) => s = s.add_error(e.into()),
},
@ -263,6 +277,7 @@ impl DirInfo {
path: impl Into<PathBuf>,
mut depth: Option<u64>,
params: &DirBuilder,
ctrl_c: Arc<AtomicBool>,
) -> Self {
if let Some(current) = depth {
if let Some(new) = current.checked_sub(1) {
@ -272,7 +287,7 @@ impl DirInfo {
}
}
let d = DirInfo::new(path, &params, depth);
let d = DirInfo::new(path, &params, depth, ctrl_c);
self.size += d.size;
self.blocks += d.blocks;
self.dirs.push(d);

View File

@ -32,6 +32,7 @@ fn get_file_type(md: &std::fs::Metadata) -> &str {
file_type
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn dir_entry_dict(
filename: &std::path::Path,
metadata: Option<&std::fs::Metadata>,
@ -40,6 +41,7 @@ pub(crate) fn dir_entry_dict(
short_name: bool,
with_symlink_targets: bool,
du: bool,
ctrl_c: Arc<AtomicBool>,
) -> Result<Value, ShellError> {
let tag = tag.into();
let mut dict = TaggedDictBuilder::new(&tag);
@ -140,7 +142,7 @@ pub(crate) fn dir_entry_dict(
false,
);
DirInfo::new(filename, &params, None).get_size()
DirInfo::new(filename, &params, None, ctrl_c).get_size()
} else {
md.len()
};

View File

@ -112,6 +112,7 @@ impl Shell for FilesystemShell {
name_tag: Tag,
ctrl_c: Arc<AtomicBool>,
) -> Result<OutputStream, ShellError> {
let ctrl_c_copy = ctrl_c.clone();
let (path, p_tag) = match path {
Some(p) => {
let p_tag = p.tag;
@ -171,6 +172,7 @@ impl Shell for FilesystemShell {
short_names,
with_symlink_targets,
du,
ctrl_c.clone()
)
.map(|entry| ReturnSuccess::Value(entry.into()))?;
@ -178,7 +180,7 @@ impl Shell for FilesystemShell {
}
};
Ok(stream.interruptible(ctrl_c).to_output_stream())
Ok(stream.interruptible(ctrl_c_copy).to_output_stream())
}
fn cd(&self, args: CdArgs, name: Tag) -> Result<OutputStream, ShellError> {