From 6a371802b45bc38bf3e04f58f82ba9f440e86377 Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Mon, 10 Feb 2020 14:32:18 -0600 Subject: [PATCH] Add block size to du (#1341) * Add block size to du * Change blocks to physical size * Use path instead of strings for file/directory names * Why don't I just use paths instead of strings anyway? * shorten physical size and apparent size to physical and apparent resp. --- Cargo.lock | 10 ++++++++ Cargo.toml | 1 + src/commands/du.rs | 61 +++++++++++++++++++++++++++++++--------------- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bbf9dbc6..5929e5663 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -931,6 +931,15 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "filesize" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a941e39ae509cebcd46c6734c20553a9a209b92cea5fc54618fe778fea61701" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "fixedbitset" version = "0.1.9" @@ -2201,6 +2210,7 @@ dependencies = [ "derive-new", "dirs 2.0.2", "dunce", + "filesize", "futures 0.3.3", "futures-util", "futures_codec", diff --git a/Cargo.toml b/Cargo.toml index efc505d60..e860997ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,6 +133,7 @@ onig_sys = {version = "=69.1.0", optional = true } crossterm = {version = "0.16.0", optional = true} url = {version = "2.1.1", optional = true} semver = {version = "0.9.0", optional = true} +filesize = "0.1.0" [target.'cfg(unix)'.dependencies] users = "0.9" diff --git a/src/commands/du.rs b/src/commands/du.rs index 219059c7d..ecd08edfa 100644 --- a/src/commands/du.rs +++ b/src/commands/du.rs @@ -1,5 +1,8 @@ +extern crate filesize; + use crate::commands::command::RunnablePerItemContext; use crate::prelude::*; +use filesize::file_real_size_fast; use glob::*; use indexmap::map::IndexMap; use nu_errors::ShellError; @@ -165,32 +168,38 @@ struct DirInfo { files: Vec, errors: Vec, size: u64, - name: String, + blocks: u64, + path: PathBuf, tag: Tag, } struct FileInfo { - name: String, + path: PathBuf, size: u64, + blocks: Option, tag: Tag, } impl FileInfo { fn new(path: impl Into, deref: bool, tag: Tag) -> Result { let path = path.into(); - let name = path.to_string_lossy().to_string(); let m = if deref { - std::fs::metadata(path) + std::fs::metadata(&path) } else { - std::fs::symlink_metadata(path) + std::fs::symlink_metadata(&path) }; match m { - Ok(d) => Ok(FileInfo { - name, - size: d.len(), - tag, - }), + Ok(d) => { + let block_size = file_real_size_fast(&path, &d).ok(); + + Ok(FileInfo { + path, + blocks: block_size, + size: d.len(), + tag, + }) + } Err(e) => Err(e.into()), } } @@ -205,11 +214,12 @@ impl DirInfo { errors: Vec::new(), files: Vec::new(), size: 0, + blocks: 0, tag: params.tag.clone(), - name: path.to_string_lossy().to_string(), + path, }; - match std::fs::read_dir(path) { + match std::fs::read_dir(&s.path) { Ok(d) => { for f in d { match f { @@ -247,6 +257,7 @@ impl DirInfo { let d = DirInfo::new(path, ¶ms, depth); self.size += d.size; + self.blocks += d.blocks; self.dirs.push(d); self } @@ -260,6 +271,7 @@ impl DirInfo { let inc = params.min.map_or(true, |s| file.size >= s); if inc { self.size += file.size; + self.blocks += file.blocks.unwrap_or(0); if params.all { self.files.push(file); } @@ -286,12 +298,16 @@ impl From for Value { fn from(d: DirInfo) -> Self { let mut r: IndexMap = IndexMap::new(); r.insert( - "size".to_string(), - UntaggedValue::bytes(d.size).into_untagged_value(), + "path".to_string(), + UntaggedValue::path(d.path).retag(d.tag.clone()), ); r.insert( - "name".to_string(), - UntaggedValue::string(d.name).into_untagged_value(), + "apparent".to_string(), + UntaggedValue::bytes(d.size).retag(d.tag.clone()), + ); + r.insert( + "physical".to_string(), + UntaggedValue::bytes(d.blocks).retag(d.tag.clone()), ); if !d.files.is_empty() { let v = Value { @@ -341,13 +357,18 @@ impl From for Value { fn from(f: FileInfo) -> Self { let mut r: IndexMap = IndexMap::new(); r.insert( - "size".to_string(), - UntaggedValue::bytes(f.size).into_untagged_value(), + "path".to_string(), + UntaggedValue::path(f.path).retag(f.tag.clone()), ); r.insert( - "name".to_string(), - UntaggedValue::string(f.name).into_untagged_value(), + "apparent".to_string(), + UntaggedValue::bytes(f.size).retag(f.tag.clone()), ); + let b = match f.blocks { + Some(k) => UntaggedValue::bytes(k).retag(f.tag.clone()), + None => UntaggedValue::nothing().retag(f.tag.clone()), + }; + r.insert("physical".to_string(), b); Value { value: UntaggedValue::row(r), tag: f.tag,