diff --git a/CHANGELOG.md b/CHANGELOG.md index d90c94d..1da2fcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,21 @@ ## Packaging +# v0.10.0 + +## Features + +- `diskus` was per default changing its behavior, if it is writing to `stdout`. This might be working well, when writing to files, but causes implicit problems, when piping e.g. into `grep` to determine large elements in a `diskus` output. + This is behavior is now made configurable via `--raw` flag and per default off. + +# v0.9.0 + +## Features + +- The default behavior for `diskus` changed, when multiple paths are passed as arguments. + Beforehand, there size was aggregated. Now `diskus` returns the sizes for each path separately. + One can still tigger aggregation via `-a/--aggregate`. + # v0.6.0 - Updated dependencies diff --git a/Cargo.lock b/Cargo.lock index 6396564..2af8cb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -11,12 +20,34 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "assert_cmd" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "libc", + "predicates 3.1.3", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "atty" version = "0.2.14" @@ -28,12 +59,41 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" + +[[package]] +name = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + [[package]] name = "clap" version = "2.34.0" @@ -42,11 +102,11 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim", "term_size", "textwrap", - "unicode-width", + "unicode-width 0.1.14", "vec_map", ] @@ -84,32 +144,85 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "diskus" -version = "0.8.0" +version = "0.9.0" dependencies = [ + "assert_cmd", "atty", "clap", "crossbeam-channel", "humansize", "num-format", "num_cpus", + "predicates 2.1.5", "rayon", + "tabwriter", "tempdir", + "tempfile", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -131,6 +244,15 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -143,6 +265,24 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "num-format" version = "0.4.4" @@ -153,6 +293,15 @@ dependencies = [ "itoa", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -163,6 +312,77 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "predicates" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +dependencies = [ + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.4.6" @@ -220,6 +440,35 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "regex" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -229,12 +478,65 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.3", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tabwriter" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce91f2f0ec87dff7e6bcbbeb267439aa1188703003c6055193c821487400432" +dependencies = [ + "unicode-width 0.2.1", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -245,6 +547,19 @@ dependencies = [ "remove_dir_all", ] +[[package]] +name = "tempfile" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + [[package]] name = "term_size" version = "0.3.2" @@ -255,6 +570,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + [[package]] name = "textwrap" version = "0.11.0" @@ -262,21 +583,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ "term_size", - "unicode-width", + "unicode-width 0.1.14", ] +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + [[package]] name = "unicode-width" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" + [[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "winapi" version = "0.3.9" @@ -298,3 +649,92 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.3", +] diff --git a/Cargo.toml b/Cargo.toml index 10fb68e..1569db1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT/Apache-2.0" name = "diskus" readme = "README.md" repository = "https://github.com/sharkdp/diskus" -version = "0.8.0" +version = "0.10.0" edition = "2021" rust-version = "1.76" @@ -18,6 +18,7 @@ num-format = "0.4" rayon = "1.0" crossbeam-channel = "0.5" atty = "0.2" +tabwriter = "1.4.1" [dependencies.clap] version = "2" @@ -25,6 +26,10 @@ features = ["suggestions", "color", "wrap_help"] [dev-dependencies] tempdir = "0.3" +assert_cmd = "2.0" +tempfile = "3.6" +predicates = "2.1" + [[bin]] name = "diskus" diff --git a/doc/diskus.1 b/doc/diskus.1 index 8ffc5c7..c8812be 100644 --- a/doc/diskus.1 +++ b/doc/diskus.1 @@ -14,9 +14,15 @@ Set the number of threads (default: 3 x num cores) Output format for file sizes (decimal: MB, binary: MiB) [default: decimal] [possible values: decimal, binary] .TP +\fB\-v\fR, \fB\-\-raw\fR +Output raw numbers of bytes and do not apply any formatting via \fB\-\-size\-format\fR. +.TP \fB\-v\fR, \fB\-\-verbose\fR Do not hide filesystem errors .TP +\fB\-a\fR, \fB\-\-aggregate\fR +Aggregate sizes of all passed filesystem paths +.TP \fB\-b\fR, \fB\-\-apparent\-size\fR Compute apparent size instead of disk usage .TP diff --git a/src/main.rs b/src/main.rs index 693003d..d7913a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,15 @@ use std::path::PathBuf; +use std::io::{self, Write}; use clap::{crate_name, crate_version, App, AppSettings, Arg}; use humansize::file_size_opts::{self, FileSizeOpts}; use humansize::FileSize; use num_format::{Locale, ToFormattedString}; +use tabwriter::TabWriter; use diskus::{Error, FilesizeType, Walk}; -fn print_result(size: u64, errors: &[Error], size_format: &FileSizeOpts, verbose: bool) { +fn build_message(path: Option<&PathBuf>, size: u64, errors: &[Error], size_format: &FileSizeOpts, raw: bool, verbose: bool) -> String { if verbose { for err in errors { match err { @@ -31,14 +33,47 @@ fn print_result(size: u64, errors: &[Error], size_format: &FileSizeOpts, verbose ); } - if atty::is(atty::Stream::Stdout) { - println!( - "{} ({:} bytes)", - size.file_size(size_format).unwrap(), - size.to_formatted_string(&Locale::en) + let path_info = path.map(|p| format!("\t{}", p.to_string_lossy())).unwrap_or_default(); + if raw { + format!("{}{}", size, path_info) + } else { + let human_readable_size = size.file_size(size_format).unwrap(); + let size_in_bytes = size.to_formatted_string(&Locale::en); + if verbose { + format!("{} ({:} bytes){}", human_readable_size, size_in_bytes, path_info) + } else { + format!("{}{}", human_readable_size, path_info) + } + } +} + + +fn perform_walks(walks: Vec, aggregate: bool, size_format: FileSizeOpts, raw: bool, verbose: bool) { + if aggregate { + let mut total_size = 0; + let mut all_errors = Vec::new(); + + for walk in walks { + let (size, errors) = walk.run(); + total_size += size; + all_errors.extend(errors); + } + + println!("{}", + build_message(None, total_size, &all_errors, &size_format, raw, verbose) ); } else { - println!("{}", size); + let mut tw = TabWriter::new(io::stdout()).padding(2); + for walk in walks { + // each Walk knows its own root_directories + let (size, errors) = walk.run(); + assert_eq!(walk.get_root_directories().len(), 1, "perform_walks can only be called without aggregation with a single root directory"); + let path = &walk.get_root_directories()[0]; + writeln!(tw, "{}", + build_message(Some(path), size, &errors, &size_format, raw, verbose) + ).unwrap(); + } + tw.flush().unwrap(); } } @@ -72,12 +107,25 @@ fn main() { .default_value("decimal") .help("Output format for file sizes (decimal: MB, binary: MiB)"), ) + .arg( + Arg::with_name("raw") + .long("raw") + .takes_value(false) + .help("Instead of human-readable sizes uses raw numbers in bytes. Makes the system ignore the parameter \"size-format\"."), + ) .arg( Arg::with_name("verbose") .long("verbose") .short("v") .takes_value(false) .help("Do not hide filesystem errors"), + ) + .arg( + Arg::with_name("aggregate") + .long("aggregate") + .short("a") + .takes_value(false) + .help("Aggregate sizes across all provided paths"), ); #[cfg(not(windows))] @@ -116,9 +164,17 @@ fn main() { _ => file_size_opts::BINARY, }; + let raw = matches.is_present("raw"); let verbose = matches.is_present("verbose"); + let aggregate = matches.is_present("aggregate"); + let walks: Vec = if aggregate { + vec![Walk::new(&paths, num_threads, filesize_type)] + } else { + paths + .iter() + .map(|p| Walk::new(std::slice::from_ref(p), num_threads, filesize_type)) + .collect() + }; - let walk = Walk::new(&paths, num_threads, filesize_type); - let (size, errors) = walk.run(); - print_result(size, &errors, &size_format, verbose); + perform_walks(walks, aggregate, size_format, raw, verbose); } diff --git a/src/walk.rs b/src/walk.rs index eed97b6..4662a29 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -76,6 +76,9 @@ impl Walk<'_> { filesize_type, } } + pub fn get_root_directories(&self) -> &[PathBuf] { + self.root_directories + } pub fn run(&self) -> (u64, Vec) { let (tx, rx) = channel::unbounded(); diff --git a/tests/aggregate.rs b/tests/aggregate.rs new file mode 100644 index 0000000..2611504 --- /dev/null +++ b/tests/aggregate.rs @@ -0,0 +1,47 @@ +use assert_cmd::Command; +use tempfile::tempdir; +use std::fs::{self, File}; +use std::io::Write; + +#[test] +fn test_diskus_output_lines() { + let tmp = tempdir().unwrap(); + let dir1 = tmp.path().join("dir1"); + let dir2 = tmp.path().join("dir2"); + fs::create_dir(&dir1).unwrap(); + fs::create_dir(&dir2).unwrap(); + + let mut f1 = File::create(dir1.join("a.txt")).unwrap(); + f1.write_all(&vec![0u8; 100]).unwrap(); + let mut f2 = File::create(dir2.join("b.txt")).unwrap(); + f2.write_all(&vec![0u8; 200]).unwrap(); + + // Testing for exact outputs, i.e. filesizes is problematic across platforms. + // Hence we just verify, that the amount of printed lines varies depending on aggregation. + + // ---- Default mode (no aggregation) ---- + let mut cmd = Command::cargo_bin("diskus").unwrap(); + cmd.arg(dir1.to_str().unwrap()) + .arg(dir2.to_str().unwrap()); + + let output = cmd.assert().success().get_output().stdout.clone(); + let out_str = String::from_utf8_lossy(&output); + + // Each path prints one header line + one size line + // e.g., "4196\tdir1" + let lines: Vec<&str> = out_str.lines().collect(); + assert_eq!(lines.len(), 2); + + // ---- Aggregate mode (-a) ---- + let mut cmd = Command::cargo_bin("diskus").unwrap(); + cmd.arg("-a") + .arg(dir1.to_str().unwrap()) + .arg(dir2.to_str().unwrap()); + + let output = cmd.assert().success().get_output().stdout.clone(); + let out_str = String::from_utf8_lossy(&output); + + let lines: Vec<&str> = out_str.lines().collect(); + assert_eq!(lines.len(), 1); // Only one line for aggregated size +} +