mirror of
https://github.com/bootandy/dust.git
synced 2025-12-07 05:10:40 -08:00
Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f395a7d768 | ||
|
|
a36eec6cae | ||
|
|
38938e005e | ||
|
|
da61b15715 | ||
|
|
0b22d0a977 | ||
|
|
356d14ac0f | ||
|
|
311bc45388 | ||
|
|
ef66fb3938 | ||
|
|
b934445e04 | ||
|
|
a6839c020f | ||
|
|
7e47d5b47a | ||
|
|
6a65570f3f | ||
|
|
a4ca78dbe4 | ||
|
|
bfbe8a57ae | ||
|
|
b4b73e45f3 | ||
|
|
78119aba0f | ||
|
|
5535478fe8 | ||
|
|
7ba91a4a22 | ||
|
|
79416fd5fc | ||
|
|
b66523cff3 | ||
|
|
19a41aa382 | ||
|
|
62ac9b623a | ||
|
|
bf28d42483 | ||
|
|
f8ce6c97bf | ||
|
|
86b3cccaf6 | ||
|
|
3c920431fa | ||
|
|
a1ece05af5 | ||
|
|
cef2c588b7 | ||
|
|
7d8e498238 | ||
|
|
53c7a69dcb | ||
|
|
9a9cbefd3d | ||
|
|
224a2c6f25 | ||
|
|
99003cbba9 | ||
|
|
c83803b440 | ||
|
|
a41862d799 | ||
|
|
6ab46d8471 | ||
|
|
c727eb2d11 | ||
|
|
0effaa7fd7 | ||
|
|
25c50f88c4 | ||
|
|
0c19a66432 | ||
|
|
4cffc4370b | ||
|
|
db6c8a019d | ||
|
|
e03094a4fa | ||
|
|
1d9a56e025 | ||
|
|
ec2d9e19d4 | ||
|
|
9fbfcb275a | ||
|
|
1c60d1e2ac | ||
|
|
fd35734a94 | ||
|
|
c6f4ace2b6 | ||
|
|
d46b63fad8 | ||
|
|
872a49bb7d | ||
|
|
04c6c204c3 | ||
|
|
7ac01e8166 | ||
|
|
2f7a88e8dc | ||
|
|
2ca2cebdad | ||
|
|
80338f4731 | ||
|
|
d327bd2e68 | ||
|
|
7db6cf2f32 | ||
|
|
76d0762c97 | ||
|
|
6e03dd77e6 | ||
|
|
4906e9efda | ||
|
|
876609f2cb | ||
|
|
12775db94b | ||
|
|
bfaf5ee173 | ||
|
|
fd68330815 | ||
|
|
0bf4ebf554 | ||
|
|
cab24f58d5 | ||
|
|
b1b933d851 | ||
|
|
6a86e8befd | ||
|
|
3fb91a6c29 | ||
|
|
51561994c5 | ||
|
|
ce0e14bf00 | ||
|
|
dd75ec4aa7 | ||
|
|
65cd42736a | ||
|
|
4792e97177 | ||
|
|
3e9f09e339 | ||
|
|
dba465a094 | ||
|
|
25d1ee7b43 | ||
|
|
2556885622 | ||
|
|
8c088a7026 | ||
|
|
39db8b86fd | ||
|
|
c5830c5d00 | ||
|
|
b68c450710 | ||
|
|
6e2e5761d8 | ||
|
|
6842526d2c | ||
|
|
4ac85d7dc9 | ||
|
|
8170a07886 | ||
|
|
0f1f823736 | ||
|
|
e6c777fb8b | ||
|
|
0bded9698a | ||
|
|
c7f0ea59f0 | ||
|
|
6d62cfb9ae | ||
|
|
803934d84b | ||
|
|
24c97ef92f | ||
|
|
270edf0a76 | ||
|
|
0c5b08e1d2 | ||
|
|
35aef4c837 | ||
|
|
95e7bb01eb | ||
|
|
247e55788a | ||
|
|
bcab66ab8b | ||
|
|
2c87a21da1 | ||
|
|
74b9178017 | ||
|
|
2eb1633b77 | ||
|
|
3fd274ab36 | ||
|
|
f3ab902811 | ||
|
|
b3b1a867c4 | ||
|
|
32561ecb18 | ||
|
|
2fe3943ed5 | ||
|
|
b8ad44b7f0 | ||
|
|
1a34bc3198 | ||
|
|
385ddb75e1 | ||
|
|
5c6165da8a | ||
|
|
f39b09e79c | ||
|
|
778dbb44b3 | ||
|
|
69c79d5f95 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -2,10 +2,8 @@
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
*.swp
|
||||
.vscode/*
|
||||
*.idea/*
|
||||
11
.travis.yml
11
.travis.yml
@@ -1,6 +1,12 @@
|
||||
# Based on the "trust" template v0.1.2
|
||||
# https://github.com/japaric/trust/tree/v0.1.2
|
||||
|
||||
# ----------- To do a release ---------
|
||||
# tag a commit and push:
|
||||
# git tag v0.4.0.1
|
||||
# git push origin v0.4.0.1
|
||||
# Remember to do a cargo publish to put it in crates.io
|
||||
|
||||
dist: trusty
|
||||
language: rust
|
||||
services: docker
|
||||
@@ -46,8 +52,9 @@ deploy:
|
||||
# - Create a `public_repo` GitHub token. Go to: https://github.com/settings/tokens/new
|
||||
# - Encrypt it: `travis encrypt 0123456789012345678901234567890123456789
|
||||
# - Paste the output down here
|
||||
api_key:
|
||||
secure: UlU73Td7Bkb2N88ws4YGLWR+4U0IMgiou9QQtMnmpouJFjeUNxtLSPMPODVXP7zq4sKt5HR5B3fX9MW4mKm351fvnQEoihETn06pKiXGnY//SlTPTt67MX9ZOYmd9ohJReMDOZDgqhnGLxfymycGtsLAmdjDZnAl+IMqgg0FMyVFj9Cl9aKxnn12lxQyX4zabHKk8TUKD3By8ZoEUnJMHt3gEtOmbDgS4brcTPeHCzqnYFw73LEnkqvz+JP0XwauJY7Cf8lminKm/klmjCkQji8T9SHI52v1g0Fxpx0ucp2o3vulQrLHXaHvZ6Fr7J0cSXXzaFF3rrGLt4t4jU/+9TZm1+n5k5XuPW4x4NTCC9NmIj/z0/z41t82E9qZhzhtm2Jdsg6H2tNk+C774TYqcmR6GCvfRadfjRp3cA5dh0UwDVjH2MJFxlHDVkl6la0mVVRsCGF3oBKZVk0BDl1womfnmI46o/uU+gLknHN6Ed6PHHPPYDViWd3VKdmHKT7XrkMMUF6HjZUtla689DWIOWZSiV++1dVPcl/1TV+6tTmN4bBtPcLuX7SHRuLp2PI2kATvRMECsa7gZRypW4jKpVn7b2yetX9TVI3i1zR5zkQJ3dPg8sATvYPL53aKH/WsqUg4rzoAlbk9so+++R4bQY69LhV3B511B7EAynoZFdM
|
||||
# api_key:
|
||||
# secure: UlU73Td7Bkb2N88ws4YGLWR+4U0IMgiou9QQtMnmpouJFjeUNxtLSPMPODVXP7zq4sKt5HR5B3fX9MW4mKm351fvnQEoihETn06pKiXGnY//SlTPTt67MX9ZOYmd9ohJReMDOZDgqhnGLxfymycGtsLAmdjDZnAl+IMqgg0FMyVFj9Cl9aKxnn12lxQyX4zabHKk8TUKD3By8ZoEUnJMHt3gEtOmbDgS4brcTPeHCzqnYFw73LEnkqvz+JP0XwauJY7Cf8lminKm/klmjCkQji8T9SHI52v1g0Fxpx0ucp2o3vulQrLHXaHvZ6Fr7J0cSXXzaFF3rrGLt4t4jU/+9TZm1+n5k5XuPW4x4NTCC9NmIj/z0/z41t82E9qZhzhtm2Jdsg6H2tNk+C774TYqcmR6GCvfRadfjRp3cA5dh0UwDVjH2MJFxlHDVkl6la0mVVRsCGF3oBKZVk0BDl1womfnmI46o/uU+gLknHN6Ed6PHHPPYDViWd3VKdmHKT7XrkMMUF6HjZUtla689DWIOWZSiV++1dVPcl/1TV+6tTmN4bBtPcLuX7SHRuLp2PI2kATvRMECsa7gZRypW4jKpVn7b2yetX9TVI3i1zR5zkQJ3dPg8sATvYPL53aKH/WsqUg4rzoAlbk9so+++R4bQY69LhV3B511B7EAynoZFdM
|
||||
api_key: $API_KEY
|
||||
file_glob: true
|
||||
file: $CRATE_NAME-$TRAVIS_TAG-$TARGET.*
|
||||
on:
|
||||
|
||||
573
Cargo.lock
generated
Normal file
573
Cargo.lock
generated
Normal file
@@ -0,0 +1,573 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_cli"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "c2-chacha"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difference"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "du-dust"
|
||||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jwalk 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "environment"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "jwalk"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
"checksum assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a29ab7c0ed62970beb0534d637a8688842506d0ff9157de83286dacd065c8149"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
||||
"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum colored 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "433e7ac7d511768127ed85b0c4947f47a254131e37864b2dc13f52aa32cd37e5"
|
||||
"checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e"
|
||||
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
||||
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
|
||||
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
||||
"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
|
||||
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
|
||||
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||
"checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee"
|
||||
"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
|
||||
"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
|
||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||
"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7"
|
||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||
"checksum jwalk 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3dbf0a8f61baee43a2918ff50ac6a2d3b2c105bc08ed53bc298779f1263409"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
|
||||
"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72"
|
||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
|
||||
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
|
||||
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
|
||||
"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||
"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
|
||||
"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
|
||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
30
Cargo.toml
30
Cargo.toml
@@ -1,8 +1,30 @@
|
||||
[package]
|
||||
name = "dust"
|
||||
version = "0.2.0"
|
||||
name = "du-dust"
|
||||
description = "A more intuitive version of du"
|
||||
version = "0.4.3"
|
||||
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
|
||||
edition = "2018"
|
||||
|
||||
documentation = "https://github.com/bootandy/dust"
|
||||
homepage = "https://github.com/bootandy/dust"
|
||||
repository = "https://github.com/bootandy/dust"
|
||||
|
||||
keywords = ["du", "command-line", "disk", "disk-usage"]
|
||||
categories = ["command-line-utilities"]
|
||||
license = "Apache-2.0"
|
||||
|
||||
[badges]
|
||||
travis-ci = {repository = "https://travis-ci.org/bootandy/dust"}
|
||||
|
||||
[[bin]]
|
||||
name = "dust"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.11"
|
||||
clap = "2.31"
|
||||
ansi_term = "=0.12"
|
||||
clap = "=2.33"
|
||||
jwalk = "0.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cli = "=0.6"
|
||||
tempfile = "=3"
|
||||
|
||||
82
README.md
82
README.md
@@ -1,43 +1,73 @@
|
||||
|
||||
[](https://travis-ci.org/bootandy/dust)
|
||||
|
||||
|
||||
# Dust
|
||||
du + rust = dust. A rust alternative to du
|
||||
|
||||
[Releases](https://github.com/bootandy/dust/releases)
|
||||
du + rust = dust. Like du but more intuitive
|
||||
|
||||
Unlike du, dust is meant to give you an instant overview of which directories are using disk space without requiring sort or head. Dust does not count file system blocks; it uses file sizes instead. Dust will print a maximum of 1 'Did not have permissions message'.
|
||||
## Install
|
||||
|
||||
#### Cargo Install
|
||||
|
||||
Dust will list the 15 biggest sub directories and will smartly recurse down the tree to find the larger ones. There is no need for a '-d' flag or a '-h' flag. The largest sub directory will have its size shown in red
|
||||
* cargo install du-dust
|
||||
|
||||
#### Download Install
|
||||
|
||||
* Download linux / mac binary from [Releases](https://github.com/bootandy/dust/releases)
|
||||
* unzip file: tar -xvf _downloaded_file.tar.gz_
|
||||
* move file to executable path: sudo mv dust /usr/local/bin/
|
||||
|
||||
## Overview
|
||||
|
||||
Dust is meant to give you an instant overview of which directories are using disk space without requiring sort or head. Dust will print a maximum of 1 'Did not have permissions message'.
|
||||
|
||||
Dust will list the 20 biggest sub directories or files and will smartly recurse down the tree to find the larger ones. There is no need for a '-d' flag or a '-h' flag. The largest sub directory will have its size shown in *red*
|
||||
|
||||
## Why?
|
||||
|
||||
du has a number of ways of showing you what it finds, in terms of disk consumption, but really, there are only one or two ways you invoke it: with -h for “human readable” units, like 100G or 89k, or with -b for “bytes”. The former is generally used for a quick survey of a directory with a small number of things in it, and the latter for when you have a bunch and need to sort the output numerically, and you’re obligated to either further pass it into something like awk to turn bytes into the appropriate human-friendly unit like mega or gigabytes, or pipe thru sort and head while remembering the '-h' flag. Then once you have the top offenders, you recurse down into the largest one and repeat the process until you’ve found your cruft or gems and can move on.
|
||||
|
||||
Dust assumes that’s what you wanted to do in the first place, and takes care of tracking the largest offenders in terms of actual size, and showing them to you with human-friendly units and in-context within the filetree.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
Usage: dust <dir>
|
||||
Usage: dust <dir> <another_dir> <and_more>
|
||||
Usage: dust -s <dir> (apparent-size - shows the length of the file as opposed to the amount of disk space it uses)
|
||||
Usage: dust -n 30 <dir> (Shows 30 directories not 15)
|
||||
Usage: dust <dir> <another_dir> <and_more>
|
||||
Usage: dust -p <dir> (full-path - does not shorten the path of the subdirectories)
|
||||
Usage: dust -s <dir> (apparent-size - shows the length of the file as opposed to the amount of disk space it uses)
|
||||
Usage: dust -n 30 <dir> (Shows 30 directories not 20)
|
||||
Usage: dust -d 3 <dir> (Shows 3 levels of subdirectories)
|
||||
Usage: dust -r <dir> (Reverse order of output, with root at the lowest)
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
djin:git/dust> dust
|
||||
65M .
|
||||
65M └─┬ ./target
|
||||
49M ├─┬ ./target/debug
|
||||
26M │ ├─┬ ./target/debug/deps
|
||||
21M │ │ └── ./target/debug/deps/libclap-9e6625ac8ff074ad.rlib
|
||||
13M │ ├── ./target/debug/dust
|
||||
8.9M │ └─┬ ./target/debug/incremental
|
||||
6.7M │ ├─┬ ./target/debug/incremental/dust-2748eiei2tcnp
|
||||
6.7M │ │ └─┬ ./target/debug/incremental/dust-2748eiei2tcnp/s-ezd6jnik5u-163pyem-1aab9ncf5glum
|
||||
3.0M │ │ └── ./target/debug/incremental/dust-2748eiei2tcnp/s-ezd6jnik5u-163pyem-1aab9ncf5glum/dep-graph.bin
|
||||
2.2M │ └─┬ ./target/debug/incremental/dust-1dlon65p8m3vl
|
||||
2.2M │ └── ./target/debug/incremental/dust-1dlon65p8m3vl/s-ezd6jncecv-1xsnfd0-4dw9l1r2th2t
|
||||
15M └─┬ ./target/release
|
||||
9.2M ├─┬ ./target/release/deps
|
||||
6.7M │ └── ./target/release/deps/libclap-87bc2534ea57f044.rlib
|
||||
5.9M └── ./target/release/dust
|
||||
1.2G target
|
||||
622M ├─┬ debug
|
||||
445M │ ├── deps
|
||||
70M │ ├── incremental
|
||||
56M │ └── build
|
||||
262M ├─┬ rls
|
||||
262M │ └─┬ debug
|
||||
203M │ ├── deps
|
||||
56M │ └── build
|
||||
165M ├─┬ package
|
||||
165M │ └─┬ du-dust-0.2.4
|
||||
165M │ └─┬ target
|
||||
165M │ └─┬ debug
|
||||
131M │ └── deps
|
||||
165M └─┬ release
|
||||
124M └── deps
|
||||
```
|
||||
Performance: dust is currently about 4 times slower than du.
|
||||
|
||||
## Performance
|
||||
|
||||
Dust uses a parallel fetching implementation that greatly improves performance for directory trees with reasonable amount of files (read more than 20) compared to du. This can be as much as 7x faster than du on a clean cache.
|
||||
|
||||
## Alternatives
|
||||
|
||||
* [NCDU](https://dev.yorhel.nl/ncdu)
|
||||
* du -d 1 -h | sort -h
|
||||
|
||||
Note: Apparent-size is calculated slightly differently in dust to gdu. In dust each hard link is counted as using file_length space. In gdu only the first entry is counted.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
# This script takes care of building your crate and packaging it for release
|
||||
|
||||
set -ex
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
main() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
# This script takes care of testing your crate
|
||||
|
||||
set -ex
|
||||
|
||||
246
src/display.rs
246
src/display.rs
@@ -1,106 +1,182 @@
|
||||
extern crate ansi_term;
|
||||
|
||||
use dust::Node;
|
||||
use std::cmp;
|
||||
use self::ansi_term::Colour::Fixed;
|
||||
use self::ansi_term::Style;
|
||||
use crate::utils::Node;
|
||||
|
||||
static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];
|
||||
|
||||
pub fn draw_it(permissions: bool, heads: &Vec<Node>, to_display: &Vec<&Node>) -> () {
|
||||
if !permissions {
|
||||
eprintln!("Did not have permissions for all directories");
|
||||
}
|
||||
|
||||
for d in to_display {
|
||||
if heads.contains(d) {
|
||||
display_node(d, &to_display, true, 1, "")
|
||||
}
|
||||
}
|
||||
pub struct DisplayData {
|
||||
pub short_paths: bool,
|
||||
pub is_reversed: bool,
|
||||
pub colors_on: bool,
|
||||
}
|
||||
|
||||
fn display_node<S: Into<String>>(
|
||||
node_to_print: &Node,
|
||||
to_display: &Vec<&Node>,
|
||||
is_first: bool,
|
||||
depth: u8,
|
||||
indentation_str: S,
|
||||
) {
|
||||
let mut is = indentation_str.into();
|
||||
print_this_node(node_to_print, is_first, depth, is.as_ref());
|
||||
|
||||
is = is.replace("└─┬", " ");
|
||||
is = is.replace("└──", " ");
|
||||
is = is.replace("├──", "│ ");
|
||||
is = is.replace("├─┬", "│ ");
|
||||
|
||||
let printable_node_slashes = node_to_print.name().matches('/').count();
|
||||
|
||||
let mut num_siblings = to_display.iter().fold(0, |a, b| {
|
||||
if node_to_print.children().contains(b)
|
||||
&& b.name().matches('/').count() == printable_node_slashes + 1
|
||||
{
|
||||
a + 1
|
||||
impl DisplayData {
|
||||
fn get_first_chars(&self) -> &str {
|
||||
if self.is_reversed {
|
||||
"─┴"
|
||||
} else {
|
||||
a
|
||||
"─┬"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let mut is_biggest = true;
|
||||
for node in to_display {
|
||||
if node_to_print.children().contains(node) {
|
||||
let has_display_children = node.children()
|
||||
.iter()
|
||||
.fold(false, |has_kids, n| has_kids || to_display.contains(&n));
|
||||
|
||||
let has_children = node.children().len() > 0 && has_display_children;
|
||||
if node.name().matches('/').count() == printable_node_slashes + 1 {
|
||||
num_siblings -= 1;
|
||||
|
||||
let tree_chars = {
|
||||
if num_siblings == 0 {
|
||||
if has_children {
|
||||
"└─┬"
|
||||
} else {
|
||||
"└──"
|
||||
}
|
||||
} else {
|
||||
if has_children {
|
||||
"├─┬"
|
||||
} else {
|
||||
"├──"
|
||||
}
|
||||
}
|
||||
};
|
||||
display_node(
|
||||
&node,
|
||||
to_display,
|
||||
is_biggest,
|
||||
depth + 1,
|
||||
is.to_string() + tree_chars,
|
||||
);
|
||||
is_biggest = false;
|
||||
#[allow(clippy::collapsible_if)]
|
||||
fn get_tree_chars(
|
||||
&self,
|
||||
num_siblings: u64,
|
||||
max_siblings: u64,
|
||||
has_children: bool,
|
||||
) -> &'static str {
|
||||
if self.is_reversed {
|
||||
if num_siblings == max_siblings - 1 {
|
||||
if has_children {
|
||||
"┌─┴"
|
||||
} else {
|
||||
"┌──"
|
||||
}
|
||||
} else if has_children {
|
||||
"├─┴"
|
||||
} else {
|
||||
"├──"
|
||||
}
|
||||
} else {
|
||||
if num_siblings == 0 {
|
||||
if has_children {
|
||||
"└─┬"
|
||||
} else {
|
||||
"└──"
|
||||
}
|
||||
} else if has_children {
|
||||
"├─┬"
|
||||
} else {
|
||||
"├──"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_this_node(node_to_print: &Node, is_biggest: bool, depth: u8, indentation_str: &str) {
|
||||
let padded_size = format!("{:>5}", human_readable_number(node_to_print.size()),);
|
||||
println!(
|
||||
"{} {} {}",
|
||||
if is_biggest {
|
||||
Fixed(196).paint(padded_size)
|
||||
fn is_biggest(&self, num_siblings: u64, max_siblings: u64) -> bool {
|
||||
if self.is_reversed {
|
||||
num_siblings == 0
|
||||
} else {
|
||||
Fixed(7).paint(padded_size)
|
||||
},
|
||||
indentation_str,
|
||||
Fixed(7)
|
||||
.on(Fixed(cmp::min(8, (depth) as u8) + 231))
|
||||
.paint(node_to_print.name().to_string())
|
||||
);
|
||||
num_siblings == max_siblings - 1
|
||||
}
|
||||
}
|
||||
|
||||
fn get_children_from_node(&self, node: Node) -> impl Iterator<Item = Node> {
|
||||
if self.is_reversed {
|
||||
let n: Vec<Node> = node.children.into_iter().rev().map(|a| a).collect();
|
||||
n.into_iter()
|
||||
} else {
|
||||
node.children.into_iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn human_readable_number(size: u64) -> (String) {
|
||||
pub fn draw_it(
|
||||
permissions: bool,
|
||||
use_full_path: bool,
|
||||
is_reversed: bool,
|
||||
no_colors: bool,
|
||||
root_node: Node,
|
||||
) {
|
||||
if !permissions {
|
||||
eprintln!("Did not have permissions for all directories");
|
||||
}
|
||||
let display_data = DisplayData {
|
||||
short_paths: !use_full_path,
|
||||
is_reversed,
|
||||
colors_on: !no_colors,
|
||||
};
|
||||
|
||||
for c in display_data.get_children_from_node(root_node) {
|
||||
let first_tree_chars = display_data.get_first_chars();
|
||||
display_node(c, true, first_tree_chars, &display_data)
|
||||
}
|
||||
}
|
||||
|
||||
fn display_node(node: Node, is_biggest: bool, indent: &str, display_data: &DisplayData) {
|
||||
let mut num_siblings = node.children.len() as u64;
|
||||
let max_sibling = num_siblings;
|
||||
let new_indent = clean_indentation_string(indent);
|
||||
let name = node.name.clone();
|
||||
let size = node.size;
|
||||
|
||||
if !display_data.is_reversed {
|
||||
print_this_node(&*name, size, is_biggest, display_data, indent);
|
||||
}
|
||||
|
||||
for c in display_data.get_children_from_node(node) {
|
||||
num_siblings -= 1;
|
||||
let chars = display_data.get_tree_chars(num_siblings, max_sibling, !c.children.is_empty());
|
||||
let is_biggest = display_data.is_biggest(num_siblings, max_sibling);
|
||||
let full_indent = new_indent.clone() + chars;
|
||||
display_node(c, is_biggest, &*full_indent, display_data)
|
||||
}
|
||||
|
||||
if display_data.is_reversed {
|
||||
print_this_node(&*name, size, is_biggest, display_data, indent);
|
||||
}
|
||||
}
|
||||
|
||||
fn clean_indentation_string(s: &str) -> String {
|
||||
let mut is: String = s.into();
|
||||
// For reversed:
|
||||
is = is.replace("┌─┴", " ");
|
||||
is = is.replace("┌──", " ");
|
||||
is = is.replace("├─┴", "│ ");
|
||||
is = is.replace("─┴", " ");
|
||||
// For normal
|
||||
is = is.replace("└─┬", " ");
|
||||
is = is.replace("└──", " ");
|
||||
is = is.replace("├─┬", "│ ");
|
||||
is = is.replace("─┬", " ");
|
||||
// For both
|
||||
is = is.replace("├──", "│ ");
|
||||
is
|
||||
}
|
||||
|
||||
fn print_this_node(
|
||||
name: &str,
|
||||
size: u64,
|
||||
is_biggest: bool,
|
||||
display_data: &DisplayData,
|
||||
indentation: &str,
|
||||
) {
|
||||
let pretty_size = format!("{:>5}", human_readable_number(size),);
|
||||
println!(
|
||||
"{}",
|
||||
format_string(name, is_biggest, display_data, &*pretty_size, indentation)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn format_string(
|
||||
dir_name: &str,
|
||||
is_biggest: bool,
|
||||
display_data: &DisplayData,
|
||||
size: &str,
|
||||
indentation: &str,
|
||||
) -> String {
|
||||
let printable_name = {
|
||||
if display_data.short_paths {
|
||||
dir_name.split('/').last().unwrap_or(dir_name)
|
||||
} else {
|
||||
dir_name
|
||||
}
|
||||
};
|
||||
format!(
|
||||
"{} {} {}",
|
||||
if is_biggest && display_data.colors_on {
|
||||
Fixed(196).paint(size)
|
||||
} else {
|
||||
Style::new().paint(size)
|
||||
},
|
||||
indentation,
|
||||
printable_name,
|
||||
)
|
||||
}
|
||||
|
||||
fn human_readable_number(size: u64) -> String {
|
||||
for (i, u) in UNITS.iter().enumerate() {
|
||||
let marker = 1024u64.pow((UNITS.len() - i) as u32);
|
||||
if size >= marker {
|
||||
|
||||
68
src/lib.rs
68
src/lib.rs
@@ -1,68 +0,0 @@
|
||||
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Node {
|
||||
name: String,
|
||||
size: u64,
|
||||
children: Vec<Node>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new<S: Into<String>>(name: S, size: u64, children: Vec<Node>) -> Self {
|
||||
Node {
|
||||
children: children,
|
||||
name: name.into(),
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn children(&self) -> &Vec<Node> {
|
||||
&self.children
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &String {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Node {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
if self.size > other.size {
|
||||
Ordering::Less
|
||||
} else if self.size < other.size {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
let my_slashes = self.name.matches('/').count();
|
||||
let other_slashes = other.name.matches('/').count();
|
||||
|
||||
if my_slashes > other_slashes {
|
||||
Ordering::Greater
|
||||
} else if my_slashes < other_slashes {
|
||||
Ordering::Less
|
||||
} else {
|
||||
if self.name < other.name {
|
||||
Ordering::Less
|
||||
} else if self.name > other.name {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Equal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Node {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialEq for Node {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(&self.name, self.size) == (&other.name, other.size)
|
||||
}
|
||||
}
|
||||
impl Eq for Node {}
|
||||
149
src/main.rs
149
src/main.rs
@@ -1,44 +1,167 @@
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate dust;
|
||||
|
||||
use clap::{App, AppSettings, Arg};
|
||||
use utils::{find_big_ones, get_dir_tree};
|
||||
use self::display::draw_it;
|
||||
use crate::utils::is_a_parent_of;
|
||||
use clap::{App, AppSettings, Arg};
|
||||
use utils::{find_big_ones, get_dir_tree, simplify_dir_names, sort, trim_deep_ones, Node};
|
||||
|
||||
mod utils;
|
||||
mod display;
|
||||
mod utils;
|
||||
|
||||
static DEFAULT_NUMBER_OF_LINES: &'static str = "15";
|
||||
static DEFAULT_NUMBER_OF_LINES: usize = 20;
|
||||
|
||||
#[cfg(windows)]
|
||||
fn init_color() {
|
||||
ansi_term::enable_ansi_support().expect("Couldn't enable color support");
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn init_color() {}
|
||||
|
||||
fn main() {
|
||||
init_color();
|
||||
let def_num_str = DEFAULT_NUMBER_OF_LINES.to_string();
|
||||
let options = App::new("Dust")
|
||||
.about("Like du but more intuitive")
|
||||
.version(crate_version!())
|
||||
.setting(AppSettings::TrailingVarArg)
|
||||
.arg(
|
||||
Arg::with_name("depth")
|
||||
.short("d")
|
||||
.long("depth")
|
||||
.help("Depth to show")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("threads")
|
||||
.short("t")
|
||||
.long("threads")
|
||||
.help("Number of threads to spawn simultaneously")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("number_of_lines")
|
||||
.short("n")
|
||||
.long("number-of-lines")
|
||||
.help("Number of lines of output to show")
|
||||
.takes_value(true)
|
||||
.default_value(DEFAULT_NUMBER_OF_LINES),
|
||||
.default_value(def_num_str.as_ref()),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("use_apparent_size")
|
||||
Arg::with_name("display_full_paths")
|
||||
.short("p")
|
||||
.long("full-paths")
|
||||
.help("If set sub directories will not have their path shortened"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("display_apparent_size")
|
||||
.short("s")
|
||||
.long("apparent-size")
|
||||
.help("If set will use file length. Otherwise we use blocks"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("reverse")
|
||||
.short("r")
|
||||
.long("reverse")
|
||||
.help("If applied tree will be printed upside down (biggest lowest)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("no_colors")
|
||||
.short("c")
|
||||
.long("no_colors")
|
||||
.help("If applied no colors will be printed (normally largest directories are marked in red"),
|
||||
)
|
||||
.arg(Arg::with_name("inputs").multiple(true))
|
||||
.get_matches();
|
||||
|
||||
let filenames = {
|
||||
let target_dirs = {
|
||||
match options.values_of("inputs") {
|
||||
None => vec!["."],
|
||||
Some(r) => r.collect(),
|
||||
}
|
||||
};
|
||||
let number_of_lines = value_t!(options.value_of("number_of_lines"), usize).unwrap();
|
||||
let use_apparent_size = options.is_present("use_apparent_size");
|
||||
|
||||
let (permissions, node_per_top_level_dir) = get_dir_tree(&filenames, use_apparent_size);
|
||||
let slice_it = find_big_ones(&node_per_top_level_dir, number_of_lines);
|
||||
draw_it(permissions, &node_per_top_level_dir, &slice_it);
|
||||
let number_of_lines = match value_t!(options.value_of("number_of_lines"), usize) {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
eprintln!("Ignoring bad value for number_of_lines");
|
||||
DEFAULT_NUMBER_OF_LINES
|
||||
}
|
||||
};
|
||||
|
||||
let threads = options.value_of("threads").and_then(|threads| {
|
||||
threads
|
||||
.parse::<usize>()
|
||||
.map_err(|_| eprintln!("Ignoring bad value for threads: {:?}", threads))
|
||||
.ok()
|
||||
});
|
||||
|
||||
let depth = options.value_of("depth").and_then(|depth| {
|
||||
depth
|
||||
.parse::<u64>()
|
||||
.map(|v| v + 1)
|
||||
.map_err(|_| eprintln!("Ignoring bad value for depth"))
|
||||
.ok()
|
||||
});
|
||||
if options.is_present("depth") && number_of_lines != DEFAULT_NUMBER_OF_LINES {
|
||||
eprintln!("Use either -n or -d. Not both");
|
||||
return;
|
||||
}
|
||||
|
||||
let use_apparent_size = options.is_present("display_apparent_size");
|
||||
|
||||
let simplified_dirs = simplify_dir_names(target_dirs);
|
||||
let (permissions, nodes) = get_dir_tree(&simplified_dirs, use_apparent_size, threads);
|
||||
let sorted_data = sort(nodes);
|
||||
let biggest_ones = {
|
||||
match depth {
|
||||
None => find_big_ones(sorted_data, number_of_lines + simplified_dirs.len()),
|
||||
Some(d) => trim_deep_ones(sorted_data, d, &simplified_dirs),
|
||||
}
|
||||
};
|
||||
let tree = build_tree(biggest_ones, depth);
|
||||
|
||||
draw_it(
|
||||
permissions,
|
||||
options.is_present("display_full_paths"),
|
||||
options.is_present("reverse"),
|
||||
options.is_present("no_colors"),
|
||||
tree,
|
||||
);
|
||||
}
|
||||
|
||||
fn build_tree(biggest_ones: Vec<(String, u64)>, depth: Option<u64>) -> Node {
|
||||
let mut top_parent = Node::default();
|
||||
|
||||
// assume sorted order
|
||||
for b in biggest_ones {
|
||||
let n = Node {
|
||||
name: b.0,
|
||||
size: b.1,
|
||||
children: Vec::default(),
|
||||
};
|
||||
recursively_build_tree(&mut top_parent, n, depth);
|
||||
}
|
||||
top_parent
|
||||
}
|
||||
|
||||
fn recursively_build_tree(parent_node: &mut Node, new_node: Node, depth: Option<u64>) {
|
||||
let new_depth = match depth {
|
||||
None => None,
|
||||
Some(0) => return,
|
||||
Some(d) => Some(d - 1),
|
||||
};
|
||||
if let Some(c) = parent_node
|
||||
.children
|
||||
.iter_mut()
|
||||
.find(|c| is_a_parent_of(&c.name, &new_node.name))
|
||||
{
|
||||
recursively_build_tree(c, new_node, new_depth);
|
||||
} else {
|
||||
parent_node.children.push(new_node);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
0
src/test_dir/many/a_file
Normal file
0
src/test_dir/many/a_file
Normal file
1
src/test_dir/many/hello_file
Normal file
1
src/test_dir/many/hello_file
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
||||
1
src/test_dir2/dir/hello
Normal file
1
src/test_dir2/dir/hello
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
||||
1
src/test_dir2/dir_name_clash
Normal file
1
src/test_dir2/dir_name_clash
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
||||
1
src/test_dir2/dir_substring/hello
Normal file
1
src/test_dir2/dir_substring/hello
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
||||
301
src/tests.rs
Normal file
301
src/tests.rs
Normal file
@@ -0,0 +1,301 @@
|
||||
use super::*;
|
||||
|
||||
use crate::display::DisplayData;
|
||||
use display::format_string;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::panic;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use tempfile::Builder;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
pub fn test_main() {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["src/test_dir"])
|
||||
.stdout()
|
||||
.is(main_output(true).as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_main_long_paths() {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-p", "src/test_dir"])
|
||||
.stdout()
|
||||
.is(main_output(false).as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_main_multi_arg() {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["src/test_dir/many/", "src/test_dir/", "src/test_dir"])
|
||||
.stdout()
|
||||
.is(main_output(true).as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn main_output(short_paths: bool) -> String {
|
||||
let d = DisplayData {
|
||||
short_paths,
|
||||
is_reversed: false,
|
||||
colors_on: true,
|
||||
};
|
||||
format!(
|
||||
"{}
|
||||
{}
|
||||
{}
|
||||
{}",
|
||||
format_string("src/test_dir", true, &d, " 4.0K", "─┬"),
|
||||
format_string("src/test_dir/many", true, &d, " 4.0K", " └─┬",),
|
||||
format_string("src/test_dir/many/hello_file", true, &d, " 4.0K", " ├──",),
|
||||
format_string("src/test_dir/many/a_file", false, &d, " 0B", " └──",),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn main_output(short_paths: bool) -> String {
|
||||
let d = DisplayData {
|
||||
short_paths,
|
||||
is_reversed: false,
|
||||
colors_on: true,
|
||||
};
|
||||
format!(
|
||||
"{}
|
||||
{}
|
||||
{}
|
||||
{}",
|
||||
format_string("src/test_dir", true, &d, " 12K", "─┬"),
|
||||
format_string("src/test_dir/many", true, &d, " 8.0K", " └─┬",),
|
||||
format_string("src/test_dir/many/hello_file", true, &d, " 4.0K", " ├──",),
|
||||
format_string("src/test_dir/many/a_file", false, &d, " 0B", " └──",),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_no_color_flag() {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-c", "src/test_dir/"])
|
||||
.stdout()
|
||||
.is(no_color_flag_output().as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn no_color_flag_output() -> String {
|
||||
"
|
||||
4.0K ─┬ test_dir
|
||||
4.0K └─┬ many
|
||||
4.0K ├── hello_file
|
||||
0B └── a_file
|
||||
"
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn no_color_flag_output() -> String {
|
||||
"
|
||||
12K ─┬ test_dir
|
||||
8.0K └─┬ many
|
||||
4.0K ├── hello_file
|
||||
0B └── a_file
|
||||
"
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_apparent_size() {
|
||||
let d = DisplayData {
|
||||
short_paths: true,
|
||||
is_reversed: false,
|
||||
colors_on: true,
|
||||
};
|
||||
let r = format!(
|
||||
"{}",
|
||||
format_string("src/test_dir/many/hello_file", true, &d, " 6B", " ├──",),
|
||||
);
|
||||
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-s", "src/test_dir"])
|
||||
.stdout()
|
||||
.contains(r.as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_reverse_flag() {
|
||||
// variable names the same length make the output easier to read
|
||||
let a = " ┌── a_file";
|
||||
let b = " ├── hello_file";
|
||||
let c = " ┌─┴ many";
|
||||
let d = " ─┴ test_dir";
|
||||
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-r", "src/test_dir"])
|
||||
.stdout()
|
||||
.contains(a)
|
||||
.stdout()
|
||||
.contains(b)
|
||||
.stdout()
|
||||
.contains(c)
|
||||
.stdout()
|
||||
.contains(d)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_d_flag_works() {
|
||||
// We should see the top level directory but not the sub dirs / files:
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-d", "1", "-s", "src/test_dir"])
|
||||
.stdout()
|
||||
.doesnt_contain("hello_file")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn build_temp_file(dir: &TempDir) -> PathBuf {
|
||||
let file_path = dir.path().join("notes.txt");
|
||||
let mut file = File::create(&file_path).unwrap();
|
||||
writeln!(file, "I am a temp file").unwrap();
|
||||
file_path
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_soft_sym_link() {
|
||||
let dir = Builder::new().tempdir().unwrap();
|
||||
let file = build_temp_file(&dir);
|
||||
let dir_s = dir.path().to_str().unwrap();
|
||||
let file_path_s = file.to_str().unwrap();
|
||||
|
||||
let link_name = dir.path().join("the_link");
|
||||
let link_name_s = link_name.to_str().unwrap();
|
||||
let c = Command::new("ln")
|
||||
.arg("-s")
|
||||
.arg(file_path_s)
|
||||
.arg(link_name_s)
|
||||
.output();
|
||||
assert!(c.is_ok());
|
||||
|
||||
let a = format!(" ─┬ {}", dir_s);
|
||||
let b = format!(" ├── {}", file_path_s);
|
||||
let c = format!(" └── {}", link_name_s);
|
||||
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-p", &dir_s])
|
||||
.stdout()
|
||||
.contains(a.as_str())
|
||||
.stdout()
|
||||
.contains(b.as_str())
|
||||
.stdout()
|
||||
.contains(c.as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Hard links are ignored as the inode is the same as the file
|
||||
#[test]
|
||||
pub fn test_hard_sym_link() {
|
||||
let dir = Builder::new().tempdir().unwrap();
|
||||
let file = build_temp_file(&dir);
|
||||
let dir_s = dir.path().to_str().unwrap();
|
||||
let file_path_s = file.to_str().unwrap();
|
||||
|
||||
let link_name = dir.path().join("the_link");
|
||||
let link_name_s = link_name.to_str().unwrap();
|
||||
let c = Command::new("ln")
|
||||
.arg(file_path_s)
|
||||
.arg(link_name_s)
|
||||
.output();
|
||||
assert!(c.is_ok());
|
||||
|
||||
let a = format!(" ─┬ {}", dir_s);
|
||||
let b = format!(" └── {}", link_name_s);
|
||||
let b2 = format!(" └── {}", file_path_s);
|
||||
|
||||
// Because this is a hard link the file and hard link look identical. Therefore
|
||||
// we cannot guarantee which version will appear first.
|
||||
let result = panic::catch_unwind(|| {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-p", dir_s])
|
||||
.stdout()
|
||||
.contains(a.as_str())
|
||||
.stdout()
|
||||
.contains(b.as_str())
|
||||
.unwrap();
|
||||
});
|
||||
if result.is_err() {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-p", dir_s])
|
||||
.stdout()
|
||||
.contains(a.as_str())
|
||||
.stdout()
|
||||
.contains(b2.as_str())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// Check we don't recurse down an infinite symlink tree
|
||||
#[test]
|
||||
pub fn test_recursive_sym_link() {
|
||||
let dir = Builder::new().tempdir().unwrap();
|
||||
let dir_s = dir.path().to_str().unwrap();
|
||||
|
||||
let link_name = dir.path().join("the_link");
|
||||
let link_name_s = link_name.to_str().unwrap();
|
||||
|
||||
let c = Command::new("ln")
|
||||
.arg("-s")
|
||||
.arg(dir_s)
|
||||
.arg(link_name_s)
|
||||
.output();
|
||||
assert!(c.is_ok());
|
||||
|
||||
let a = format!(" ─┬ {}", dir_s);
|
||||
let b = format!(" └── {}", link_name_s);
|
||||
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-p", dir_s])
|
||||
.stdout()
|
||||
.contains(a.as_str())
|
||||
.stdout()
|
||||
.contains(b.as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Check against directories and files whos names are substrings of each other
|
||||
#[test]
|
||||
pub fn test_substring_of_names() {
|
||||
assert_cli::Assert::main_binary()
|
||||
.with_args(&["-c", "src/test_dir2"])
|
||||
.stdout()
|
||||
.is(no_substring_of_names_output().as_str())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn no_substring_of_names_output() -> String {
|
||||
"
|
||||
24K ─┬ test_dir2
|
||||
8.0K ├─┬ dir
|
||||
4.0K │ └── hello
|
||||
8.0K ├─┬ dir_substring
|
||||
4.0K │ └── hello
|
||||
4.0K └── dir_name_clash
|
||||
"
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn no_substring_of_names_output() -> String {
|
||||
"
|
||||
12K ─┬ test_dir2
|
||||
4.0K ├─┬ dir
|
||||
4.0K │ └── hello
|
||||
4.0K ├── dir_name_clash
|
||||
4.0K └─┬ dir_substring
|
||||
4.0K └── hello
|
||||
"
|
||||
.into()
|
||||
}
|
||||
307
src/utils/mod.rs
307
src/utils/mod.rs
@@ -1,113 +1,254 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use std::fs::{self, ReadDir};
|
||||
use std::io;
|
||||
|
||||
use dust::Node;
|
||||
use jwalk::WalkDir;
|
||||
|
||||
mod platform;
|
||||
use self::platform::*;
|
||||
|
||||
pub fn get_dir_tree(filenames: &Vec<&str>, apparent_size: bool) -> (bool, Vec<Node>) {
|
||||
let mut permissions = true;
|
||||
let mut results = vec![];
|
||||
for &b in filenames {
|
||||
let mut new_name = String::from(b);
|
||||
while new_name.chars().last() == Some('/') && new_name.len() != 1 {
|
||||
new_name.pop();
|
||||
}
|
||||
let (hp, data) = examine_dir_str(&new_name, apparent_size);
|
||||
permissions = permissions && hp;
|
||||
results.push(data);
|
||||
}
|
||||
(permissions, results)
|
||||
#[derive(Debug, Default, Eq)]
|
||||
pub struct Node {
|
||||
pub name: String,
|
||||
pub size: u64,
|
||||
pub children: Vec<Node>,
|
||||
}
|
||||
|
||||
fn examine_dir_str(loc: &str, apparent_size: bool) -> (bool, Node) {
|
||||
let mut inodes: HashSet<(u64, u64)> = HashSet::new();
|
||||
let (hp, result) = examine_dir(fs::read_dir(loc), apparent_size, &mut inodes);
|
||||
impl Ord for Node {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
if self.size == other.size {
|
||||
self.name.cmp(&other.name)
|
||||
} else {
|
||||
self.size.cmp(&other.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This needs to be folded into the below recursive call somehow
|
||||
let new_size = result.iter().fold(0, |a, b| a + b.size());
|
||||
(hp, Node::new(loc, new_size, result))
|
||||
impl PartialOrd for Node {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Node {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name && self.size == other.size && self.children == other.children
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_a_parent_of(parent: &str, child: &str) -> bool {
|
||||
(child.starts_with(parent) && child.chars().nth(parent.chars().count()) == Some('/')) || parent == "/"
|
||||
}
|
||||
|
||||
pub fn simplify_dir_names(filenames: Vec<&str>) -> HashSet<String> {
|
||||
let mut top_level_names: HashSet<String> = HashSet::with_capacity(filenames.len());
|
||||
let mut to_remove: Vec<String> = Vec::with_capacity(filenames.len());
|
||||
|
||||
for t in filenames {
|
||||
let top_level_name = strip_end_slash(t);
|
||||
let mut can_add = true;
|
||||
|
||||
for tt in top_level_names.iter() {
|
||||
if is_a_parent_of(&top_level_name, tt) {
|
||||
to_remove.push(tt.to_string());
|
||||
} else if is_a_parent_of(tt, &top_level_name) {
|
||||
can_add = false;
|
||||
}
|
||||
}
|
||||
to_remove.sort_unstable();
|
||||
top_level_names.retain(|tr| to_remove.binary_search(tr).is_err());
|
||||
to_remove.clear();
|
||||
if can_add {
|
||||
top_level_names.insert(strip_end_slash(t).to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
top_level_names
|
||||
}
|
||||
|
||||
pub fn get_dir_tree(
|
||||
top_level_names: &HashSet<String>,
|
||||
apparent_size: bool,
|
||||
threads: Option<usize>,
|
||||
) -> (bool, HashMap<String, u64>) {
|
||||
let mut permissions = 0;
|
||||
let mut inodes: HashSet<(u64, u64)> = HashSet::new();
|
||||
let mut data: HashMap<String, u64> = HashMap::new();
|
||||
|
||||
for b in top_level_names.iter() {
|
||||
examine_dir(
|
||||
&b,
|
||||
apparent_size,
|
||||
&mut inodes,
|
||||
&mut data,
|
||||
&mut permissions,
|
||||
threads,
|
||||
);
|
||||
}
|
||||
(permissions == 0, data)
|
||||
}
|
||||
|
||||
pub fn strip_end_slash(mut new_name: &str) -> &str {
|
||||
while (new_name.ends_with('/') || new_name.ends_with("/.")) && new_name.len() > 1 {
|
||||
new_name = &new_name[..new_name.len() - 1];
|
||||
}
|
||||
new_name
|
||||
}
|
||||
|
||||
fn examine_dir(
|
||||
a_dir: io::Result<ReadDir>,
|
||||
top_dir: &str,
|
||||
apparent_size: bool,
|
||||
inodes: &mut HashSet<(u64, u64)>,
|
||||
) -> (bool, Vec<Node>) {
|
||||
let mut result = vec![];
|
||||
let mut have_permission = true;
|
||||
data: &mut HashMap<String, u64>,
|
||||
file_count_no_permission: &mut u64,
|
||||
threads: Option<usize>,
|
||||
) {
|
||||
let mut iter = WalkDir::new(top_dir)
|
||||
.preload_metadata(true)
|
||||
.skip_hidden(false);
|
||||
if let Some(threads_to_start) = threads {
|
||||
iter = iter.num_threads(threads_to_start);
|
||||
}
|
||||
for entry in iter {
|
||||
if let Ok(e) = entry {
|
||||
let maybe_size_and_inode = get_metadata(&e, apparent_size);
|
||||
|
||||
if a_dir.is_ok() {
|
||||
let paths = a_dir.unwrap();
|
||||
for dd in paths {
|
||||
match dd {
|
||||
Ok(d) => {
|
||||
let file_type = d.file_type().ok();
|
||||
let maybe_size_and_inode = get_metadata(&d, apparent_size);
|
||||
|
||||
match (file_type, maybe_size_and_inode) {
|
||||
(Some(file_type), Some((size, inode))) => {
|
||||
let s = d.path().to_string_lossy().to_string();
|
||||
if !apparent_size {
|
||||
if let Some(inode_dev_pair) = inode {
|
||||
if inodes.contains(&inode_dev_pair) {
|
||||
continue;
|
||||
}
|
||||
inodes.insert(inode_dev_pair);
|
||||
}
|
||||
}
|
||||
|
||||
if d.path().is_dir() && !file_type.is_symlink() {
|
||||
let (hp, recursive) =
|
||||
examine_dir(fs::read_dir(d.path()), apparent_size, inodes);
|
||||
have_permission = have_permission && hp;
|
||||
let new_size = recursive.iter().fold(size, |a, b| a + b.size());
|
||||
result.push(Node::new(s, new_size, recursive))
|
||||
} else {
|
||||
result.push(Node::new(s, size, vec![]))
|
||||
match maybe_size_and_inode {
|
||||
Some((size, maybe_inode)) => {
|
||||
if !apparent_size {
|
||||
if let Some(inode_dev_pair) = maybe_inode {
|
||||
if inodes.contains(&inode_dev_pair) {
|
||||
continue;
|
||||
}
|
||||
inodes.insert(inode_dev_pair);
|
||||
}
|
||||
}
|
||||
// This path and all its parent paths have their counter incremented
|
||||
for path_name in e.path().ancestors() {
|
||||
// This is required due to bug in Jwalk that adds '/' to all sub dir lists
|
||||
// see: https://github.com/jessegrosjean/jwalk/issues/13
|
||||
if path_name.to_string_lossy() == "/" && top_dir != "/" {
|
||||
continue
|
||||
}
|
||||
let path_name = path_name.to_string_lossy();
|
||||
let s = data.entry(path_name.to_string()).or_insert(0);
|
||||
*s += size;
|
||||
if path_name == top_dir {
|
||||
break;
|
||||
}
|
||||
(_, None) => have_permission = false,
|
||||
(_, _) => (),
|
||||
}
|
||||
}
|
||||
Err(_) => (),
|
||||
None => *file_count_no_permission += 1,
|
||||
}
|
||||
} else {
|
||||
*file_count_no_permission += 1
|
||||
}
|
||||
} else {
|
||||
have_permission = false;
|
||||
}
|
||||
(have_permission, result)
|
||||
}
|
||||
|
||||
// We start with a list of root directories - these must be the biggest folders
|
||||
// We then repeadedly merge in the children of the biggest directory - Each iteration
|
||||
// the next biggest directory's children are merged in.
|
||||
pub fn find_big_ones<'a>(l: &'a Vec<Node>, max_to_show: usize) -> Vec<&Node> {
|
||||
let mut new_l: Vec<&Node> = l.iter().map(|a| a).collect();
|
||||
new_l.sort();
|
||||
|
||||
for processed_pointer in 0..max_to_show {
|
||||
if new_l.len() == processed_pointer {
|
||||
break;
|
||||
}
|
||||
// Must be a list of pointers into new_l otherwise b_list will go out of scope
|
||||
// when it is deallocated
|
||||
let mut b_list: Vec<&Node> = new_l[processed_pointer]
|
||||
.children()
|
||||
.iter()
|
||||
.map(|a| a)
|
||||
.collect();
|
||||
new_l.extend(b_list);
|
||||
new_l.sort();
|
||||
pub fn sort_by_size_first_name_second(a: &(String, u64), b: &(String, u64)) -> Ordering {
|
||||
let result = b.1.cmp(&a.1);
|
||||
if result == Ordering::Equal {
|
||||
a.0.cmp(&b.0)
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
if new_l.len() > max_to_show {
|
||||
new_l[0..max_to_show + 1].to_vec()
|
||||
pub fn sort(data: HashMap<String, u64>) -> Vec<(String, u64)> {
|
||||
let mut new_l: Vec<(String, u64)> = data.iter().map(|(a, b)| (a.clone(), *b)).collect();
|
||||
new_l.sort_unstable_by(sort_by_size_first_name_second);
|
||||
new_l
|
||||
}
|
||||
|
||||
pub fn find_big_ones(new_l: Vec<(String, u64)>, max_to_show: usize) -> Vec<(String, u64)> {
|
||||
if max_to_show > 0 && new_l.len() > max_to_show {
|
||||
new_l[0..max_to_show].to_vec()
|
||||
} else {
|
||||
new_l
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trim_deep_ones(
|
||||
input: Vec<(String, u64)>,
|
||||
max_depth: u64,
|
||||
top_level_names: &HashSet<String>,
|
||||
) -> Vec<(String, u64)> {
|
||||
let mut result: Vec<(String, u64)> = Vec::with_capacity(input.len() * top_level_names.len());
|
||||
|
||||
for name in top_level_names {
|
||||
let my_max_depth = name.matches('/').count() + max_depth as usize;
|
||||
let name_ref: &str = name.as_ref();
|
||||
|
||||
for &(ref k, ref v) in input.iter() {
|
||||
if k.starts_with(name_ref) && k.matches('/').count() <= my_max_depth {
|
||||
result.push((k.clone(), *v));
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
mod tests {
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_simplify_dir() {
|
||||
let mut correct = HashSet::new();
|
||||
correct.insert("a".to_string());
|
||||
assert_eq!(simplify_dir_names(vec!["a"]), correct);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simplify_dir_rm_subdir() {
|
||||
let mut correct = HashSet::new();
|
||||
correct.insert("a/b".to_string());
|
||||
assert_eq!(simplify_dir_names(vec!["a/b", "a/b/c", "a/b/d/f"]), correct);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simplify_dir_duplicates() {
|
||||
let mut correct = HashSet::new();
|
||||
correct.insert("a/b".to_string());
|
||||
correct.insert("c".to_string());
|
||||
assert_eq!(simplify_dir_names(vec!["a/b", "a/b//", "c", "c/"]), correct);
|
||||
}
|
||||
#[test]
|
||||
fn test_simplify_dir_rm_subdir_and_not_substrings() {
|
||||
let mut correct = HashSet::new();
|
||||
correct.insert("b".to_string());
|
||||
correct.insert("c/a/b".to_string());
|
||||
correct.insert("a/b".to_string());
|
||||
assert_eq!(simplify_dir_names(vec!["a/b", "c/a/b/", "b"]), correct);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simplify_dir_dots() {
|
||||
let mut correct = HashSet::new();
|
||||
correct.insert("src".to_string());
|
||||
assert_eq!(simplify_dir_names(vec!["src/."]), correct);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simplify_dir_substring_names() {
|
||||
let mut correct = HashSet::new();
|
||||
correct.insert("src".to_string());
|
||||
correct.insert("src_v2".to_string());
|
||||
assert_eq!(simplify_dir_names(vec!["src/", "src_v2"]), correct);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_a_parent_of() {
|
||||
assert!(is_a_parent_of("/usr", "/usr/andy"));
|
||||
assert!(is_a_parent_of("/usr", "/usr/andy/i/am/descendant"));
|
||||
assert!(!is_a_parent_of("/usr/andy", "/usr"));
|
||||
assert!(!is_a_parent_of("/usr/andy", "/usr/sibling"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_a_parent_of_root() {
|
||||
assert!(is_a_parent_of("/", "/usr/andy"));
|
||||
assert!(is_a_parent_of("/", "/usr"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +1,31 @@
|
||||
use std;
|
||||
use jwalk::DirEntry;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
fn get_block_size() -> u64 {
|
||||
// All os specific implementations of MetatdataExt seem to define a block as 512 bytes
|
||||
// https://doc.rust-lang.org/std/os/linux/fs/trait.MetadataExt.html#tymethod.st_blocks
|
||||
512
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_metadata(
|
||||
d: &std::fs::DirEntry,
|
||||
use_apparent_size: bool,
|
||||
) -> Option<(u64, Option<(u64, u64)>)> {
|
||||
use std::os::linux::fs::MetadataExt;
|
||||
match d.metadata().ok() {
|
||||
Some(md) => {
|
||||
let inode = Some((md.st_ino(), md.st_dev()));
|
||||
if use_apparent_size {
|
||||
Some((md.len(), inode))
|
||||
} else {
|
||||
Some((md.st_blocks() * get_block_size(), inode))
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "unix")]
|
||||
pub fn get_metadata(
|
||||
d: &std::fs::DirEntry,
|
||||
use_apparent_size: bool,
|
||||
) -> Option<(u64, Option<(u64, u64)>)> {
|
||||
#[cfg(target_family = "unix")]
|
||||
pub fn get_metadata(d: &DirEntry, use_apparent_size: bool) -> Option<(u64, Option<(u64, u64)>)> {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
match d.metadata().ok() {
|
||||
Some(md) => {
|
||||
let inode = Some((md.ino(), md.dev()));
|
||||
if use_apparent_size {
|
||||
Some((md.len(), inode))
|
||||
} else {
|
||||
Some((md.blocks() * get_block_size(), inode))
|
||||
}
|
||||
d.metadata.as_ref().unwrap().as_ref().ok().map(|md| {
|
||||
let inode = Some((md.ino(), md.dev()));
|
||||
if use_apparent_size {
|
||||
(md.len(), inode)
|
||||
} else {
|
||||
(md.blocks() * get_block_size(), inode)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn get_metadata(
|
||||
d: &std::fs::DirEntry,
|
||||
use_apparent_size: bool,
|
||||
) -> Option<(u64, Option<(u64, u64)>)> {
|
||||
use std::os::macos::fs::MetadataExt;
|
||||
match d.metadata().ok() {
|
||||
Some(md) => {
|
||||
let inode = Some((md.st_ino(), md.st_dev()));
|
||||
if use_apparent_size {
|
||||
Some((md.len(), inode))
|
||||
} else {
|
||||
Some((md.st_blocks() * get_block_size(), inode))
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "unix", target_os = "macos")))]
|
||||
pub fn get_metadata(d: &std::fs::DirEntry, _apparent: bool) -> Option<(u64, Option<(u64, u64)>)> {
|
||||
match d.metadata().ok() {
|
||||
Some(md) => Some((md.len(), None)),
|
||||
None => None,
|
||||
}
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
pub fn get_metadata(d: &DirEntry, _apparent: bool) -> Option<(u64, Option<(u64, u64)>)> {
|
||||
d.metadata
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.ok()
|
||||
.map(|md| (md.len(), None))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user