Compare commits

..

2 Commits

Author SHA1 Message Date
andy.boot c2546684c6 Increment version
(skipped several due to build difficulties)
2021-09-19 13:33:03 +01:00
andy.boot 96f1e5c048 Revert "Fix ci: Github actions: Publish step"
This reverts commit 5116c1c8a1.
2021-09-19 13:32:46 +01:00
15 changed files with 376 additions and 411 deletions
+7 -12
View File
@@ -81,8 +81,6 @@ jobs:
matrix: matrix:
job: job:
# { os, target, cargo-options, features, use-cross, toolchain } # { os, target, cargo-options, features, use-cross, toolchain }
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , use-cross: use-cross }
- { os: ubuntu-latest , target: aarch64-unknown-linux-musl , use-cross: use-cross }
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , use-cross: use-cross } - { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , use-cross: use-cross }
- { os: ubuntu-20.04 , target: i686-unknown-linux-gnu , use-cross: use-cross } - { os: ubuntu-20.04 , target: i686-unknown-linux-gnu , use-cross: use-cross }
- { os: ubuntu-20.04 , target: i686-unknown-linux-musl , use-cross: use-cross } - { os: ubuntu-20.04 , target: i686-unknown-linux-musl , use-cross: use-cross }
@@ -101,7 +99,6 @@ jobs:
run: | run: |
case ${{ matrix.job.target }} in case ${{ matrix.job.target }} in
arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;; arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install binutils-aarch64-linux-gnu ;;
esac esac
- name: Initialize workflow variables - name: Initialize workflow variables
id: vars id: vars
@@ -137,7 +134,7 @@ jobs:
echo ::set-output name=REF_TAG::${REF_TAG} echo ::set-output name=REF_TAG::${REF_TAG}
echo ::set-output name=REF_SHAS::${REF_SHAS} echo ::set-output name=REF_SHAS::${REF_SHAS}
# parse target # parse target
unset TARGET_ARCH ; case ${{ matrix.job.target }} in arm-unknown-linux-gnueabihf) TARGET_ARCH=arm ;; aarch-*) TARGET_ARCH=aarch64 ;; i686-*) TARGET_ARCH=i686 ;; x86_64-*) TARGET_ARCH=x86_64 ;; esac; unset TARGET_ARCH ; case ${{ matrix.job.target }} in arm-unknown-linux-gnueabihf) TARGET_ARCH=arm ;; i686-*) TARGET_ARCH=i686 ;; x86_64-*) TARGET_ARCH=x86_64 ;; esac;
echo set-output name=TARGET_ARCH::${TARGET_ARCH} echo set-output name=TARGET_ARCH::${TARGET_ARCH}
echo ::set-output name=TARGET_ARCH::${TARGET_ARCH} echo ::set-output name=TARGET_ARCH::${TARGET_ARCH}
unset TARGET_OS ; case ${{ matrix.job.target }} in *-linux-*) TARGET_OS=linux ;; *-apple-*) TARGET_OS=macos ;; *-windows-*) TARGET_OS=windows ;; esac; unset TARGET_OS ; case ${{ matrix.job.target }} in *-linux-*) TARGET_OS=linux ;; *-apple-*) TARGET_OS=macos ;; *-windows-*) TARGET_OS=windows ;; esac;
@@ -169,16 +166,16 @@ jobs:
echo ::set-output name=CARGO_USE_CROSS::${CARGO_USE_CROSS} echo ::set-output name=CARGO_USE_CROSS::${CARGO_USE_CROSS}
# # * `arm` cannot be tested on ubuntu-* hosts (b/c testing is currently primarily done via comparison of target outputs with built-in outputs and the `arm` target is not executable on the host) # # * `arm` cannot be tested on ubuntu-* hosts (b/c testing is currently primarily done via comparison of target outputs with built-in outputs and the `arm` target is not executable on the host)
JOB_DO_TESTING="true" JOB_DO_TESTING="true"
case ${{ matrix.job.target }} in arm-*|aarch64-*) unset JOB_DO_TESTING ;; esac; case ${{ matrix.job.target }} in arm-*) unset JOB_DO_TESTING ;; esac;
echo set-output name=JOB_DO_TESTING::${JOB_DO_TESTING:-<empty>/false} echo set-output name=JOB_DO_TESTING::${JOB_DO_TESTING:-<empty>/false}
echo ::set-output name=JOB_DO_TESTING::${JOB_DO_TESTING} echo ::set-output name=JOB_DO_TESTING::${JOB_DO_TESTING}
# # * test only binary for arm-type targets # # * test only binary for arm-type targets
unset CARGO_TEST_OPTIONS unset CARGO_TEST_OPTIONS
unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-*|aarch64-*) CARGO_TEST_OPTIONS="--bin ${PROJECT_NAME}" ;; esac; unset CARGO_TEST_OPTIONS ; case ${{ matrix.job.target }} in arm-*) CARGO_TEST_OPTIONS="--bin ${PROJECT_NAME}" ;; esac;
echo set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS} echo set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS}
echo ::set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS} echo ::set-output name=CARGO_TEST_OPTIONS::${CARGO_TEST_OPTIONS}
# * strip executable? # * strip executable?
STRIP="strip" ; case ${{ matrix.job.target }} in arm-unknown-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;; *-pc-windows-msvc) STRIP="" ;; aarch64-unknown-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;; aarch64-unknown-linux-musl) STRIP="" ;;esac; STRIP="strip" ; case ${{ matrix.job.target }} in arm-unknown-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;; *-pc-windows-msvc) STRIP="" ;; esac;
echo set-output name=STRIP::${STRIP} echo set-output name=STRIP::${STRIP}
echo ::set-output name=STRIP::${STRIP} echo ::set-output name=STRIP::${STRIP}
- name: Create all needed build/work directories - name: Create all needed build/work directories
@@ -213,13 +210,13 @@ jobs:
with: with:
command: install command: install
args: cargo-deb args: cargo-deb
if: matrix.job.target == 'i686-unknown-linux-musl' || matrix.job.target == 'x86_64-unknown-linux-musl' if: ${{ contains(matrix.job.target, 'musl') }}
- name: Build deb - name: Build deb
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: deb command: deb
args: --no-build --target=${{ matrix.job.target }} args: --no-build --target=${{ matrix.job.target }}
if: matrix.job.target == 'i686-unknown-linux-musl' || matrix.job.target == 'x86_64-unknown-linux-musl' if: ${{ contains(matrix.job.target, 'musl') }}
- name: Test - name: Test
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
@@ -236,7 +233,7 @@ jobs:
with: with:
name: ${{ env.PROJECT_NAME }}-${{ matrix.job.target }}.deb name: ${{ env.PROJECT_NAME }}-${{ matrix.job.target }}.deb
path: target/${{ matrix.job.target }}/debian path: target/${{ matrix.job.target }}/debian
if: matrix.job.target == 'i686-unknown-linux-musl' || matrix.job.target == 'x86_64-unknown-linux-musl' if: ${{ contains(matrix.job.target, 'musl') }}
- name: Package - name: Package
shell: bash shell: bash
run: | run: |
@@ -260,8 +257,6 @@ jobs:
with: with:
files: | files: |
${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_NAME }} ${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_NAME }}
target/${{ matrix.job.target }}/debian/*.deb
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Generated
+133 -93
View File
@@ -11,6 +11,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "ansi_term" name = "ansi_term"
version = "0.12.1" version = "0.12.1"
@@ -47,9 +56,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
@@ -59,9 +68,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "0.2.17" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"memchr", "memchr",
@@ -76,25 +85,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "3.1.2" version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5177fac1ab67102d8989464efd043c6ff44191b1557ec1ddd489b4f7e1447e77" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [ dependencies = [
"ansi_term 0.11.0",
"atty", "atty",
"bitflags", "bitflags",
"indexmap",
"lazy_static",
"os_str_bytes",
"strsim", "strsim",
"termcolor", "term_size",
"textwrap", "textwrap",
"unicode-width",
"vec_map",
] ]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.2" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
@@ -113,9 +122,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.7" version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
@@ -126,9 +135,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.7" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"lazy_static", "lazy_static",
@@ -148,9 +157,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "du-dust" name = "du-dust"
version = "0.8.0" version = "0.7.5"
dependencies = [ dependencies = [
"ansi_term", "ansi_term 0.12.1",
"assert_cmd", "assert_cmd",
"clap", "clap",
"lscolors", "lscolors",
@@ -171,20 +180,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]] [[package]]
name = "fastrand" name = "getrandom"
version = "1.7.0" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [ dependencies = [
"instant", "cfg-if",
"libc",
"wasi",
] ]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@@ -194,30 +199,11 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "indexmap"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.3" version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [ dependencies = [
"either", "either",
] ]
@@ -230,9 +216,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.119" version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
[[package]] [[package]]
name = "lscolors" name = "lscolors"
@@ -240,7 +226,7 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d24b894c45c9da468621cdd615a5a79ee5e5523dd4f75c76ebc03d458940c16e" checksum = "d24b894c45c9da468621cdd615a5a79ee5e5523dd4f75c76ebc03d458940c16e"
dependencies = [ dependencies = [
"ansi_term", "ansi_term 0.12.1",
] ]
[[package]] [[package]]
@@ -251,37 +237,34 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.6.5" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.13.1" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
] ]
[[package]] [[package]]
name = "os_str_bytes" name = "ppv-lite86"
version = "6.0.0" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "predicates" name = "predicates"
version = "2.1.1" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" checksum = "c143348f141cc87aab5b950021bac6145d0e5ae754b0591de23244cee42c9308"
dependencies = [ dependencies = [
"difflib", "difflib",
"itertools", "itertools",
@@ -290,18 +273,58 @@ dependencies = [
[[package]] [[package]]
name = "predicates-core" name = "predicates-core"
version = "1.0.3" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451"
[[package]] [[package]]
name = "predicates-tree" name = "predicates-tree"
version = "1.0.5" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" checksum = "d7dd0fd014130206c9352efbdc92be592751b2b9274dff685348341082c6ea3d"
dependencies = [ dependencies = [
"predicates-core", "predicates-core",
"termtree", "treeline",
]
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
] ]
[[package]] [[package]]
@@ -340,9 +363,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.5" version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@@ -378,9 +401,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "stfu8" name = "stfu8"
version = "0.2.5" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "019f0c664fd85d5a87dcfb62b40b691055392a35a6e59f4df83d4b770db7e876" checksum = "4bf70433e3300a3c395d06606a700cdf4205f4f14dbae2c6833127c6bb22db77"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"regex", "regex",
@@ -388,31 +411,32 @@ dependencies = [
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.3.0" version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fastrand",
"libc", "libc",
"rand",
"redox_syscall", "redox_syscall",
"remove_dir_all", "remove_dir_all",
"winapi", "winapi",
] ]
[[package]] [[package]]
name = "termcolor" name = "term_size"
version = "1.1.2" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
dependencies = [ dependencies = [
"winapi-util", "libc",
"winapi",
] ]
[[package]] [[package]]
@@ -425,17 +449,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "termtree"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b"
[[package]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.14.2" version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"term_size",
"unicode-width",
]
[[package]] [[package]]
name = "thousands" name = "thousands"
@@ -444,10 +466,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
[[package]] [[package]]
name = "unicode-width" name = "treeline"
version = "0.1.9" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "wait-timeout" name = "wait-timeout"
@@ -458,6 +492,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
+2 -2
View File
@@ -1,7 +1,7 @@
[package] [package]
name = "du-dust" name = "du-dust"
description = "A more intuitive version of du" description = "A more intuitive version of du"
version = "0.8.0" version = "0.7.5"
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"] authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
edition = "2018" edition = "2018"
readme = "README.md" readme = "README.md"
@@ -23,7 +23,7 @@ path = "src/main.rs"
[dependencies] [dependencies]
ansi_term = "0.12" ansi_term = "0.12"
clap = { version = "=3", features=["cargo"] } clap = { version = "=2.33", features = ["wrap_help"] }
lscolors = "0.7" lscolors = "0.7"
terminal_size = "0.1" terminal_size = "0.1"
unicode-width = "0.1" unicode-width = "0.1"
-8
View File
@@ -26,14 +26,6 @@ Because I want an easy way to see where my disk is being used.
* `brew tap tgotwig/linux-dust && brew install dust` * `brew tap tgotwig/linux-dust && brew install dust`
#### [Pacstall](https://github.com/pacstall/pacstall) (Debian/Ubuntu)
* `pacstall -I dust-bin`
#### Windows:
* Windows GNU version - works
* Windows MSVC - requires: [VCRUNTIME140.dll](https://docs.microsoft.com/en-gb/cpp/windows/latest-supported-vc-redist?view=msvc-170)
#### Download #### Download
* Download Linux/Mac binary from [Releases](https://github.com/bootandy/dust/releases) * Download Linux/Mac binary from [Releases](https://github.com/bootandy/dust/releases)
+15 -24
View File
@@ -18,10 +18,10 @@ use std::fs::DirEntry;
use crate::platform::get_metadata; use crate::platform::get_metadata;
pub struct WalkData<'a> { pub struct WalkData {
pub ignore_directories: HashSet<PathBuf>, pub ignore_directories: HashSet<PathBuf>,
pub filter_regex: &'a [Regex], pub filter_regex: Option<Regex>,
pub invert_filter_regex: &'a [Regex], pub invert_filter_regex: Option<Regex>,
pub allowed_filesystems: HashSet<u64>, pub allowed_filesystems: HashSet<u64>,
pub use_apparent_size: bool, pub use_apparent_size: bool,
pub by_filecount: bool, pub by_filecount: bool,
@@ -34,7 +34,7 @@ pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: WalkData) -> (Vec<Node>, bool)
let top_level_nodes: Vec<_> = dirs let top_level_nodes: Vec<_> = dirs
.into_iter() .into_iter()
.filter_map(|d| { .filter_map(|d| {
let n = walk(d, &permissions_flag, &walk_data, 0); let n = walk(d, &permissions_flag, &walk_data);
match n { match n {
Some(n) => { Some(n) => {
let mut inodes: HashSet<(u64, u64)> = HashSet::new(); let mut inodes: HashSet<(u64, u64)> = HashSet::new();
@@ -73,7 +73,6 @@ fn clean_inodes(
size: x.size + new_children.iter().map(|c| c.size).sum::<u64>(), size: x.size + new_children.iter().map(|c| c.size).sum::<u64>(),
children: new_children, children: new_children,
inode_device: x.inode_device, inode_device: x.inode_device,
depth: x.depth,
}); });
} }
@@ -91,17 +90,17 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
} }
} }
// Keeping `walk_data.filter_regex.is_empty()` is important for performance reasons, it stops unnecessary work // Keeping `walk_data.filter_regex.is_some()` is important for performance reasons, it stops unnecessary work
if !walk_data.filter_regex.is_empty() if walk_data.filter_regex.is_some()
&& entry.path().is_file() && entry.path().is_file()
&& is_filtered_out_due_to_regex(walk_data.filter_regex, &entry.path()) && is_filtered_out_due_to_regex(&walk_data.filter_regex, &entry.path())
{ {
return true; return true;
} }
if !walk_data.invert_filter_regex.is_empty() if walk_data.invert_filter_regex.is_some()
&& entry.path().is_file() && entry.path().is_file()
&& is_filtered_out_due_to_invert_regex(walk_data.invert_filter_regex, &entry.path()) && is_filtered_out_due_to_invert_regex(&walk_data.invert_filter_regex, &entry.path())
{ {
return true; return true;
} }
@@ -109,12 +108,7 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
(is_dot_file && walk_data.ignore_hidden) || is_ignored_path (is_dot_file && walk_data.ignore_hidden) || is_ignored_path
} }
fn walk( fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Option<Node> {
dir: PathBuf,
permissions_flag: &AtomicBool,
walk_data: &WalkData,
depth: usize,
) -> Option<Node> {
let mut children = vec![]; let mut children = vec![];
if let Ok(entries) = fs::read_dir(dir.clone()) { if let Ok(entries) = fs::read_dir(dir.clone()) {
@@ -132,18 +126,17 @@ fn walk(
if !ignore_file(entry, walk_data) { if !ignore_file(entry, walk_data) {
if let Ok(data) = entry.file_type() { if let Ok(data) = entry.file_type() {
if data.is_dir() && !data.is_symlink() { if data.is_dir() && !data.is_symlink() {
return walk(entry.path(), permissions_flag, walk_data, depth + 1); return walk(entry.path(), permissions_flag, walk_data);
} }
return build_node( return build_node(
entry.path(), entry.path(),
vec![], vec![],
walk_data.filter_regex, &walk_data.filter_regex,
walk_data.invert_filter_regex, &walk_data.invert_filter_regex,
walk_data.use_apparent_size, walk_data.use_apparent_size,
data.is_symlink(), data.is_symlink(),
data.is_file(), data.is_file(),
walk_data.by_filecount, walk_data.by_filecount,
depth + 1,
); );
} }
} }
@@ -159,13 +152,12 @@ fn walk(
build_node( build_node(
dir, dir,
children, children,
walk_data.filter_regex, &walk_data.filter_regex,
walk_data.invert_filter_regex, &walk_data.invert_filter_regex,
walk_data.use_apparent_size, walk_data.use_apparent_size,
false, false,
false, false,
walk_data.by_filecount, walk_data.by_filecount,
depth,
) )
} }
@@ -180,7 +172,6 @@ mod tests {
size: 10, size: 10,
children: vec![], children: vec![],
inode_device: Some((5, 6)), inode_device: Some((5, 6)),
depth: 0,
} }
} }
+39 -57
View File
@@ -28,7 +28,6 @@ pub struct DisplayData {
pub base_size: u64, pub base_size: u64,
pub longest_string_length: usize, pub longest_string_length: usize,
pub ls_colors: LsColors, pub ls_colors: LsColors,
pub iso: bool,
} }
impl DisplayData { impl DisplayData {
@@ -84,13 +83,13 @@ impl DrawData<'_> {
} }
// TODO: can we test this? // TODO: can we test this?
fn generate_bar(&self, node: &DisplayNode) -> String { fn generate_bar(&self, node: &DisplayNode, level: usize) -> String {
let chars_in_bar = self.percent_bar.chars().count(); let chars_in_bar = self.percent_bar.chars().count();
let num_bars = chars_in_bar as f32 * self.display_data.percent_size(node); let num_bars = chars_in_bar as f32 * self.display_data.percent_size(node);
let mut num_not_my_bar = (chars_in_bar as i32) - num_bars as i32; let mut num_not_my_bar = (chars_in_bar as i32) - num_bars as i32;
let mut new_bar = "".to_string(); let mut new_bar = "".to_string();
let idx = 5 - min(4, max(1, node.depth)); let idx = 5 - min(4, max(1, level));
for c in self.percent_bar.chars() { for c in self.percent_bar.chars() {
num_not_my_bar -= 1; num_not_my_bar -= 1;
@@ -114,9 +113,13 @@ pub fn draw_it(
no_percents: bool, no_percents: bool,
terminal_width: usize, terminal_width: usize,
by_filecount: bool, by_filecount: bool,
root_node: DisplayNode, option_root_node: Option<DisplayNode>,
iso: bool,
) { ) {
if option_root_node.is_none() {
return;
}
let root_node = option_root_node.unwrap();
let num_chars_needed_on_left_most = if by_filecount { let num_chars_needed_on_left_most = if by_filecount {
let max_size = root_node.size; let max_size = root_node.size;
max_size.separate_with_commas().chars().count() max_size.separate_with_commas().chars().count()
@@ -124,20 +127,15 @@ pub fn draw_it(
5 // Under normal usage we need 5 chars to display the size of a directory 5 // Under normal usage we need 5 chars to display the size of a directory
}; };
assert!( let terminal_width = terminal_width - 9 - num_chars_needed_on_left_most;
terminal_width > num_chars_needed_on_left_most + 2,
"Not enough terminal width"
);
let allowed_width = terminal_width - num_chars_needed_on_left_most - 2;
let num_indent_chars = 3; let num_indent_chars = 3;
let longest_string_length = let longest_string_length =
find_longest_dir_name(&root_node, num_indent_chars, allowed_width, !use_full_path); find_longest_dir_name(&root_node, num_indent_chars, terminal_width, !use_full_path);
let max_bar_length = if no_percents || longest_string_length + 7 >= allowed_width as usize { let max_bar_length = if no_percents || longest_string_length >= terminal_width as usize {
0 0
} else { } else {
allowed_width as usize - longest_string_length - 7 terminal_width as usize - longest_string_length
}; };
let first_size_bar = repeat(BLOCKS[0]).take(max_bar_length).collect::<String>(); let first_size_bar = repeat(BLOCKS[0]).take(max_bar_length).collect::<String>();
@@ -151,7 +149,6 @@ pub fn draw_it(
base_size: root_node.size, base_size: root_node.size,
longest_string_length, longest_string_length,
ls_colors: LsColors::from_env().unwrap_or_default(), ls_colors: LsColors::from_env().unwrap_or_default(),
iso,
}; };
let draw_data = DrawData { let draw_data = DrawData {
indent: "".to_string(), indent: "".to_string(),
@@ -181,8 +178,10 @@ fn find_longest_dir_name(
} }
fn display_node(node: DisplayNode, draw_data: &DrawData, is_biggest: bool, is_last: bool) { fn display_node(node: DisplayNode, draw_data: &DrawData, is_biggest: bool, is_last: bool) {
// hacky way of working out how deep we are in the tree
let indent = draw_data.get_new_indent(!node.children.is_empty(), is_last); let indent = draw_data.get_new_indent(!node.children.is_empty(), is_last);
let bar_text = draw_data.generate_bar(&node); let level = ((indent.chars().count() - 1) / 2) - 1;
let bar_text = draw_data.generate_bar(&node, level);
let to_print = format_string( let to_print = format_string(
&node, &node,
@@ -258,10 +257,7 @@ fn pad_or_trim_filename(node: &DisplayNode, indent: &str, display_data: &Display
let indent_and_name = format!("{} {}", indent, name); let indent_and_name = format!("{} {}", indent, name);
let width = UnicodeWidthStr::width(&*indent_and_name); let width = UnicodeWidthStr::width(&*indent_and_name);
assert!( assert!(display_data.longest_string_length >= width);
display_data.longest_string_length >= width,
"Terminal width not wide enough to draw directory tree"
);
// Add spaces after the filename so we can draw the % used bar chart. // Add spaces after the filename so we can draw the % used bar chart.
let name_and_padding = name let name_and_padding = name
@@ -269,19 +265,15 @@ fn pad_or_trim_filename(node: &DisplayNode, indent: &str, display_data: &Display
.repeat(display_data.longest_string_length - width) .repeat(display_data.longest_string_length - width)
.as_str(); .as_str();
name_and_padding maybe_trim_filename(name_and_padding, display_data)
} }
fn maybe_trim_filename(name_in: String, indent: &str, display_data: &DisplayData) -> String { fn maybe_trim_filename(name_in: String, display_data: &DisplayData) -> String {
let indent_length = UnicodeWidthStr::width(indent); if UnicodeWidthStr::width(&*name_in) > display_data.longest_string_length {
assert!( let name = name_in
display_data.longest_string_length >= indent_length + 2, .chars()
"Terminal width not wide enough to draw directory tree" .take(display_data.longest_string_length - 2)
); .collect::<String>();
let max_size = display_data.longest_string_length - indent_length;
if UnicodeWidthStr::width(&*name_in) > max_size {
let name = name_in.chars().take(max_size - 2).collect::<String>();
name + ".." name + ".."
} else { } else {
name_in name_in
@@ -314,7 +306,7 @@ fn get_name_percent(
(percents, name_and_padding) (percents, name_and_padding)
} else { } else {
let n = get_printable_name(&node.name, display_data.short_paths); let n = get_printable_name(&node.name, display_data.short_paths);
let name = maybe_trim_filename(n, indent, display_data); let name = maybe_trim_filename(n, display_data);
("".into(), name) ("".into(), name)
} }
} }
@@ -326,7 +318,7 @@ fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayD
display_data.num_chars_needed_on_left_most - size_as_str.chars().count(); display_data.num_chars_needed_on_left_most - size_as_str.chars().count();
size_as_str + " ".repeat(spaces_to_add).as_str() size_as_str + " ".repeat(spaces_to_add).as_str()
} else { } else {
format!("{:>5}", human_readable_number(node.size, display_data.iso)) format!("{:>5}", human_readable_number(node.size))
}; };
if is_biggest && display_data.colors_on { if is_biggest && display_data.colors_on {
@@ -355,10 +347,9 @@ fn get_pretty_name(
} }
} }
fn human_readable_number(size: u64, iso: bool) -> String { fn human_readable_number(size: u64) -> String {
for (i, u) in UNITS.iter().enumerate() { for (i, u) in UNITS.iter().enumerate() {
let num: u64 = if iso { 1000 } else { 1024 }; let marker = 1024u64.pow((UNITS.len() - i) as u32);
let marker = num.pow((UNITS.len() - i) as u32);
if size >= marker { if size >= marker {
if size / marker < 10 { if size / marker < 10 {
return format!("{:.1}{}", (size as f32 / marker as f32), u); return format!("{:.1}{}", (size as f32 / marker as f32), u);
@@ -387,7 +378,6 @@ mod tests {
base_size: 1, base_size: 1,
longest_string_length, longest_string_length,
ls_colors: LsColors::from_env().unwrap_or_default(), ls_colors: LsColors::from_env().unwrap_or_default(),
iso: false,
} }
} }
@@ -396,7 +386,6 @@ mod tests {
let n = DisplayNode { let n = DisplayNode {
name: PathBuf::from("/short"), name: PathBuf::from("/short"),
size: 2_u64.pow(12), // This is 4.0K size: 2_u64.pow(12), // This is 4.0K
depth: 1,
children: vec![], children: vec![],
}; };
let indent = "┌─┴"; let indent = "┌─┴";
@@ -408,7 +397,7 @@ mod tests {
indent, indent,
percent_bar, percent_bar,
is_biggest, is_biggest,
&get_fake_display_data(20), &get_fake_display_data(6),
); );
assert_eq!(s, " 4.0K ┌─┴ short"); assert_eq!(s, " 4.0K ┌─┴ short");
} }
@@ -419,7 +408,6 @@ mod tests {
let n = DisplayNode { let n = DisplayNode {
name: PathBuf::from(name), name: PathBuf::from(name),
size: 2_u64.pow(12), // This is 4.0K size: 2_u64.pow(12), // This is 4.0K
depth: 1,
children: vec![], children: vec![],
}; };
let indent = "┌─┴"; let indent = "┌─┴";
@@ -430,27 +418,21 @@ mod tests {
let s = format_string(&n, indent, percent_bar, is_biggest, &dd); let s = format_string(&n, indent, percent_bar, is_biggest, &dd);
assert_eq!( assert_eq!(
s, s,
" 4.0K ┌─┴ very_long_name_longer_than_the_eighty_character_limit_very_.." " 4.0K ┌─┴ very_long_name_longer_than_the_eighty_character_limit_very_lon.."
); );
} }
#[test] #[test]
fn test_human_readable_number() { fn test_human_readable_number() {
assert_eq!(human_readable_number(1, false), "1B"); assert_eq!(human_readable_number(1), "1B");
assert_eq!(human_readable_number(956, false), "956B"); assert_eq!(human_readable_number(956), "956B");
assert_eq!(human_readable_number(1004, false), "1004B"); assert_eq!(human_readable_number(1004), "1004B");
assert_eq!(human_readable_number(1024, false), "1.0K"); assert_eq!(human_readable_number(1024), "1.0K");
assert_eq!(human_readable_number(1536, false), "1.5K"); assert_eq!(human_readable_number(1536), "1.5K");
assert_eq!(human_readable_number(1024 * 512, false), "512K"); assert_eq!(human_readable_number(1024 * 512), "512K");
assert_eq!(human_readable_number(1024 * 1024, false), "1.0M"); assert_eq!(human_readable_number(1024 * 1024), "1.0M");
assert_eq!( assert_eq!(human_readable_number(1024 * 1024 * 1024 - 1), "1023M");
human_readable_number(1024 * 1024 * 1024 - 1, false), assert_eq!(human_readable_number(1024 * 1024 * 1024 * 20), "20G");
"1023M" assert_eq!(human_readable_number(1024 * 1024 * 1024 * 1024), "1.0T");
);
assert_eq!(human_readable_number(1024 * 1024 * 1024 * 20, false), "20G");
assert_eq!(
human_readable_number(1024 * 1024 * 1024 * 1024, false),
"1.0T"
);
} }
} }
-1
View File
@@ -5,7 +5,6 @@ use std::path::PathBuf;
pub struct DisplayNode { pub struct DisplayNode {
pub name: PathBuf, //todo: consider moving to a string? pub name: PathBuf, //todo: consider moving to a string?
pub size: u64, pub size: u64,
pub depth: usize,
pub children: Vec<DisplayNode>, pub children: Vec<DisplayNode>,
} }
+37 -14
View File
@@ -5,10 +5,18 @@ use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::path::PathBuf; use std::path::PathBuf;
pub fn get_by_depth(top_level_nodes: Vec<Node>, n: usize) -> Option<DisplayNode> {
if top_level_nodes.is_empty() {
// perhaps change this, bring back Error object?
return None;
}
let root = get_new_root(top_level_nodes);
Some(build_by_depth(&root, n - 1))
}
pub fn get_biggest( pub fn get_biggest(
top_level_nodes: Vec<Node>, top_level_nodes: Vec<Node>,
n: usize, n: usize,
depth: usize,
using_a_filter: bool, using_a_filter: bool,
) -> Option<DisplayNode> { ) -> Option<DisplayNode> {
if top_level_nodes.is_empty() { if top_level_nodes.is_empty() {
@@ -22,14 +30,14 @@ pub fn get_biggest(
let mut allowed_nodes = HashSet::new(); let mut allowed_nodes = HashSet::new();
allowed_nodes.insert(&root.name); allowed_nodes.insert(&root.name);
heap = add_children(using_a_filter, &root, depth, heap); heap = add_children(using_a_filter, &root, heap);
for _ in number_top_level_nodes..n { for _ in number_top_level_nodes..n {
let line = heap.pop(); let line = heap.pop();
match line { match line {
Some(line) => { Some(line) => {
allowed_nodes.insert(&line.name); allowed_nodes.insert(&line.name);
heap = add_children(using_a_filter, line, depth, heap); heap = add_children(using_a_filter, line, heap);
} }
None => break, None => break,
} }
@@ -51,7 +59,6 @@ pub fn get_all_file_types(top_level_nodes: Vec<Node>, n: usize) -> Option<Displa
let remaining = DisplayNode { let remaining = DisplayNode {
name: PathBuf::from("(others)"), name: PathBuf::from("(others)"),
size: rest.iter().map(|a| a.size).sum(), size: rest.iter().map(|a| a.size).sum(),
depth: 1,
children: vec![], children: vec![],
}; };
@@ -63,7 +70,6 @@ pub fn get_all_file_types(top_level_nodes: Vec<Node>, n: usize) -> Option<Displa
let result = DisplayNode { let result = DisplayNode {
name: PathBuf::from("(total)"), name: PathBuf::from("(total)"),
size: displayed.iter().map(|a| a.size).sum(), size: displayed.iter().map(|a| a.size).sum(),
depth: 0,
children: displayed, children: displayed,
}; };
Some(result) Some(result)
@@ -71,20 +77,17 @@ pub fn get_all_file_types(top_level_nodes: Vec<Node>, n: usize) -> Option<Displa
fn add_children<'a>( fn add_children<'a>(
using_a_filter: bool, using_a_filter: bool,
file_or_folder: &'a Node, line: &'a Node,
depth: usize,
mut heap: BinaryHeap<&'a Node>, mut heap: BinaryHeap<&'a Node>,
) -> BinaryHeap<&'a Node> { ) -> BinaryHeap<&'a Node> {
if depth > file_or_folder.depth {
if using_a_filter { if using_a_filter {
file_or_folder.children.iter().for_each(|c| { line.children.iter().for_each(|c| {
if c.name.is_file() || c.size > 0 { if c.name.is_file() || c.size > 0 {
heap.push(c) heap.push(c)
} }
}); });
} else { } else {
file_or_folder.children.iter().for_each(|c| heap.push(c)); line.children.iter().for_each(|c| heap.push(c));
}
} }
heap heap
} }
@@ -100,7 +103,6 @@ fn build_by_all_file_types(top_level_nodes: Vec<Node>, counter: &mut HashMap<Str
let mut display_node = counter.entry(key.clone()).or_insert(DisplayNode { let mut display_node = counter.entry(key.clone()).or_insert(DisplayNode {
name: PathBuf::from(key), name: PathBuf::from(key),
size: 0, size: 0,
depth: node.depth,
children: vec![], children: vec![],
}); });
display_node.size += node.size; display_node.size += node.size;
@@ -109,6 +111,29 @@ fn build_by_all_file_types(top_level_nodes: Vec<Node>, counter: &mut HashMap<Str
} }
} }
fn build_by_depth(node: &Node, depth: usize) -> DisplayNode {
let new_children = {
if depth == 0 {
vec![]
} else {
let mut new_children: Vec<_> = node
.children
.iter()
.map(|c| build_by_depth(c, depth - 1))
.collect();
new_children.sort();
new_children.reverse();
new_children
}
};
DisplayNode {
name: node.name.clone(),
size: node.size,
children: new_children,
}
}
fn get_new_root(top_level_nodes: Vec<Node>) -> Node { fn get_new_root(top_level_nodes: Vec<Node>) -> Node {
if top_level_nodes.len() > 1 { if top_level_nodes.len() > 1 {
let total_size = top_level_nodes.iter().map(|node| node.size).sum(); let total_size = top_level_nodes.iter().map(|node| node.size).sum();
@@ -117,7 +142,6 @@ fn get_new_root(top_level_nodes: Vec<Node>) -> Node {
size: total_size, size: total_size,
children: top_level_nodes, children: top_level_nodes,
inode_device: None, inode_device: None,
depth: 0,
} }
} else { } else {
top_level_nodes.into_iter().next().unwrap() top_level_nodes.into_iter().next().unwrap()
@@ -144,7 +168,6 @@ fn recursive_rebuilder<'a>(
let newnode = DisplayNode { let newnode = DisplayNode {
name: current.name.clone(), name: current.name.clone(),
size: current.size, size: current.size,
depth: current.depth,
children: new_children, children: new_children,
}; };
Some(newnode) Some(newnode)
+85 -98
View File
@@ -1,3 +1,4 @@
#[macro_use]
extern crate clap; extern crate clap;
extern crate rayon; extern crate rayon;
extern crate regex; extern crate regex;
@@ -7,10 +8,10 @@ use std::collections::HashSet;
use std::process; use std::process;
use self::display::draw_it; use self::display::draw_it;
use clap::{crate_version, Arg}; use clap::{App, AppSettings, Arg};
use clap::{Command, Values}; use dir_walker::walk_it;
use dir_walker::{walk_it, WalkData}; use dir_walker::WalkData;
use filter::{get_all_file_types, get_biggest}; use filter::{get_all_file_types, get_biggest, get_by_depth};
use regex::Regex; use regex::Regex;
use std::cmp::max; use std::cmp::max;
use std::path::PathBuf; use std::path::PathBuf;
@@ -82,142 +83,139 @@ fn get_width_of_terminal() -> usize {
} }
} }
fn get_regex_value(maybe_value: Option<Values>) -> Vec<Regex> { fn get_regex_value(maybe_value: Option<&str>) -> Option<Regex> {
let mut result = vec![]; match maybe_value {
if let Some(v) = maybe_value { Some(v) => match Regex::new(v) {
for reg in v { Ok(r) => Some(r),
match Regex::new(reg) {
Ok(r) => result.push(r),
Err(e) => { Err(e) => {
eprintln!("Ignoring bad value for regex {:?}", e); eprintln!("Ignoring bad value for regex {:?}", e);
process::exit(1); process::exit(1);
} }
},
None => None,
} }
}
}
result
} }
fn main() { fn main() {
let options = Command::new("Dust") let default_height = get_height_of_terminal();
let def_num_str = default_height.to_string();
let options = App::new("Dust")
.about("Like du but more intuitive") .about("Like du but more intuitive")
.version(crate_version!()) .version(crate_version!())
.trailing_var_arg(true) .setting(AppSettings::TrailingVarArg)
.arg( .arg(
Arg::new("depth") Arg::with_name("depth")
.short('d') .short("d")
.long("depth") .long("depth")
.help("Depth to show") .help("Depth to show")
.takes_value(true) .takes_value(true)
.default_value(usize::MAX.to_string().as_ref()) .conflicts_with("number_of_lines"),
) )
.arg( .arg(
Arg::new("number_of_lines") Arg::with_name("number_of_lines")
.short('n') .short("n")
.long("number-of-lines") .long("number-of-lines")
.help("Number of lines of output to show. (Default is terminal_height - 10)") .help("Number of lines of output to show. This is Height, (but h is help)")
.takes_value(true) .takes_value(true)
.default_value(def_num_str.as_ref()),
) )
.arg( .arg(
Arg::new("display_full_paths") Arg::with_name("display_full_paths")
.short('p') .short("p")
.long("full-paths") .long("full-paths")
.help("Subdirectories will not have their path shortened"), .help("Subdirectories will not have their path shortened"),
) )
.arg( .arg(
Arg::new("ignore_directory") Arg::with_name("ignore_directory")
.short('X') .short("X")
.long("ignore-directory") .long("ignore-directory")
.takes_value(true) .takes_value(true)
.number_of_values(1) .number_of_values(1)
.multiple_occurrences(true) .multiple(true)
.help("Exclude any file or directory with this name"), .help("Exclude any file or directory with this name"),
) )
.arg( .arg(
Arg::new("limit_filesystem") Arg::with_name("limit_filesystem")
.short('x') .short("x")
.long("limit-filesystem") .long("limit-filesystem")
.help("Only count the files and directories on the same filesystem as the supplied directory"), .help("Only count the files and directories on the same filesystem as the supplied directory"),
) )
.arg( .arg(
Arg::new("display_apparent_size") Arg::with_name("display_apparent_size")
.short('s') .short("s")
.long("apparent-size") .long("apparent-size")
.help("Use file length instead of blocks"), .help("Use file length instead of blocks"),
) )
.arg( .arg(
Arg::new("reverse") Arg::with_name("reverse")
.short('r') .short("r")
.long("reverse") .long("reverse")
.help("Print tree upside down (biggest highest)"), .help("Print tree upside down (biggest highest)"),
) )
.arg( .arg(
Arg::new("no_colors") Arg::with_name("no_colors")
.short('c') .short("c")
.long("no-colors") .long("no-colors")
.help("No colors will be printed (Useful for commands like: watch)"), .help("No colors will be printed (normally largest directories are colored)"),
) )
.arg( .arg(
Arg::new("no_bars") Arg::with_name("no_bars")
.short('b') .short("b")
.long("no-percent-bars") .long("no-percent-bars")
.help("No percent bars or percentages will be displayed"), .help("No percent bars or percentages will be displayed"),
) )
.arg( .arg(
Arg::new("by_filecount") Arg::with_name("by_filecount")
.short('f') .short("f")
.long("filecount") .long("filecount")
.help("Directory 'size' is number of child files/dirs not disk size"), .help("Directory 'size' is number of child files/dirs not disk size"),
) )
.arg( .arg(
Arg::new("ignore_hidden") Arg::with_name("ignore_hidden")
.short('i') // Do not use 'h' this is used by 'help' .short("i") // Do not use 'h' this is used by 'help'
.long("ignore_hidden") .long("ignore_hidden") //TODO: fix change - -> _
.help("Do not display hidden files"), .help("Do not display hidden files"),
) )
.arg( .arg(
Arg::new("invert_filter") Arg::with_name("invert_filter")
.short('v') .short("v")
.long("invert-filter") .long("invert-filter")
.takes_value(true) .takes_value(true)
.number_of_values(1) .number_of_values(1)
.multiple_occurrences(true) .multiple(true)
.conflicts_with("filter") .conflicts_with("filter")
.conflicts_with("types") .conflicts_with("types")
.help("Exclude filepaths matching this regex. To ignore png files type: -v \"\\.png$\" "), .conflicts_with("depth")
.help("Exclude files matching this regex. To ignore png files type: -v \"\\.png$\" "),
) )
.arg( .arg(
Arg::new("filter") Arg::with_name("filter")
.short('e') .short("e")
.long("filter") .long("filter")
.takes_value(true) .takes_value(true)
.number_of_values(1) .number_of_values(1)
.multiple_occurrences(true) .multiple(true)
.conflicts_with("types") .conflicts_with("types")
.help("Only include filepaths matching this regex. For png files type: -e \"\\.png$\" "), .conflicts_with("depth")
.help("Only include files matching this regex. For png files type: -e \"\\.png$\" "),
) )
.arg( .arg(
Arg::new("types") Arg::with_name("types")
.short('t') .short("t")
.long("file_types") .long("file_types")
.conflicts_with("depth") .conflicts_with("depth")
.help("show only these file types"), .help("show only these file types"),
) )
.arg( .arg(
Arg::new("width") Arg::with_name("width")
.short('w') .short("w")
.long("terminal_width") .long("terminal_width")
.takes_value(true) .takes_value(true)
.number_of_values(1) .number_of_values(1)
.help("Specify width of output overriding the auto detection of terminal width"), .help("Specify width of output overriding the auto detection of terminal width"),
) )
.arg(Arg::new("inputs").multiple_occurrences(true).default_value(".")) .arg(Arg::with_name("inputs").multiple(true).default_value("."))
.arg(
Arg::new("iso")
.short('H')
.long("si")
.help("print sizes in powers of 1000 (e.g., 1.1G)")
)
.get_matches(); .get_matches();
let target_dirs = options let target_dirs = options
@@ -227,40 +225,30 @@ fn main() {
let summarize_file_types = options.is_present("types"); let summarize_file_types = options.is_present("types");
let filter_regexs = get_regex_value(options.values_of("filter")); let maybe_filter = get_regex_value(options.value_of("filter"));
let invert_filter_regexs = get_regex_value(options.values_of("invert_filter")); let maybe_invert_filter = get_regex_value(options.value_of("invert_filter"));
let terminal_width = match options.value_of_t("width") { let number_of_lines = match value_t!(options.value_of("number_of_lines"), usize) {
Ok(v) => v, Ok(v) => v,
Err(_) => get_width_of_terminal(),
};
let depth = match options.value_of_t("depth") {
Ok(v) => v,
Err(_) => {
eprintln!("Ignoring bad value for depth");
usize::MAX
}
};
// If depth is set we set the default number_of_lines to be max
// instead of screen height
let default_height = if depth != usize::MAX {
usize::MAX
} else {
get_height_of_terminal()
};
let number_of_lines = match options.value_of("number_of_lines") {
Some(v) => match v.parse::<usize>() {
Ok(num_lines) => num_lines,
Err(_) => { Err(_) => {
eprintln!("Ignoring bad value for number_of_lines"); eprintln!("Ignoring bad value for number_of_lines");
default_height default_height
} }
},
None => default_height,
}; };
let terminal_width = match value_t!(options.value_of("width"), usize) {
Ok(v) => v,
Err(_) => get_width_of_terminal(),
};
let depth = options.value_of("depth").and_then(|depth| {
depth
.parse::<usize>()
.map(|v| v + 1)
.map_err(|_| eprintln!("Ignoring bad value for depth"))
.ok()
});
let no_colors = init_color(options.is_present("no_colors")); let no_colors = init_color(options.is_present("no_colors"));
let use_apparent_size = options.is_present("display_apparent_size"); let use_apparent_size = options.is_present("display_apparent_size");
let ignore_directories: Vec<PathBuf> = options let ignore_directories: Vec<PathBuf> = options
@@ -288,8 +276,8 @@ fn main() {
let walk_data = WalkData { let walk_data = WalkData {
ignore_directories: ignored_full_path, ignore_directories: ignored_full_path,
filter_regex: &filter_regexs, filter_regex: maybe_filter,
invert_filter_regex: &invert_filter_regexs, invert_filter_regex: maybe_invert_filter,
allowed_filesystems, allowed_filesystems,
use_apparent_size, use_apparent_size,
by_filecount, by_filecount,
@@ -301,30 +289,29 @@ fn main() {
let tree = { let tree = {
match (depth, summarize_file_types) { match (depth, summarize_file_types) {
(_, true) => get_all_file_types(top_level_nodes, number_of_lines), (_, true) => get_all_file_types(top_level_nodes, number_of_lines),
(depth, _) => get_biggest( (Some(depth), _) => get_by_depth(top_level_nodes, depth),
(_, _) => get_biggest(
top_level_nodes, top_level_nodes,
number_of_lines, number_of_lines,
depth,
options.values_of("filter").is_some() options.values_of("filter").is_some()
|| options.value_of("invert_filter").is_some(), || options.value_of("invert_filter").is_some(),
), ),
} }
}; };
if options.is_present("filter") {
println!("Filtering by: {}", options.value_of("filter").unwrap());
}
if has_errors { if has_errors {
eprintln!("Did not have permissions for all directories"); eprintln!("Did not have permissions for all directories");
} }
match tree { draw_it(
None => {}
Some(root_node) => draw_it(
options.is_present("display_full_paths"), options.is_present("display_full_paths"),
!options.is_present("reverse"), !options.is_present("reverse"),
no_colors, no_colors,
options.is_present("no_bars"), options.is_present("no_bars"),
terminal_width, terminal_width,
by_filecount, by_filecount,
root_node, tree,
options.is_present("iso"), );
),
}
} }
+2 -5
View File
@@ -12,20 +12,18 @@ pub struct Node {
pub size: u64, pub size: u64,
pub children: Vec<Node>, pub children: Vec<Node>,
pub inode_device: Option<(u64, u64)>, pub inode_device: Option<(u64, u64)>,
pub depth: usize,
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn build_node( pub fn build_node(
dir: PathBuf, dir: PathBuf,
children: Vec<Node>, children: Vec<Node>,
filter_regex: &[Regex], filter_regex: &Option<Regex>,
invert_filter_regex: &[Regex], invert_filter_regex: &Option<Regex>,
use_apparent_size: bool, use_apparent_size: bool,
is_symlink: bool, is_symlink: bool,
is_file: bool, is_file: bool,
by_filecount: bool, by_filecount: bool,
depth: usize,
) -> Option<Node> { ) -> Option<Node> {
match get_metadata(&dir, use_apparent_size) { match get_metadata(&dir, use_apparent_size) {
Some(data) => { Some(data) => {
@@ -52,7 +50,6 @@ pub fn build_node(
size, size,
children, children,
inode_device, inode_device,
depth,
}) })
} }
None => None, None => None,
+2 -2
View File
@@ -114,8 +114,8 @@ pub fn get_metadata(d: &Path, _use_apparent_size: bool) -> Option<(u64, Option<(
let attr_filtered = md.file_attributes() let attr_filtered = md.file_attributes()
& !(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM); & !(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM);
if (attr_filtered & FILE_ATTRIBUTE_ARCHIVE) != 0 if attr_filtered == FILE_ATTRIBUTE_ARCHIVE
|| (attr_filtered & FILE_ATTRIBUTE_DIRECTORY) != 0 || attr_filtered == FILE_ATTRIBUTE_DIRECTORY
|| md.file_attributes() == FILE_ATTRIBUTE_NORMAL || md.file_attributes() == FILE_ATTRIBUTE_NORMAL
{ {
Some((md.len(), None)) Some((md.len(), None))
+15 -16
View File
@@ -7,10 +7,11 @@ use regex::Regex;
pub fn simplify_dir_names<P: AsRef<Path>>(filenames: Vec<P>) -> HashSet<PathBuf> { pub fn simplify_dir_names<P: AsRef<Path>>(filenames: Vec<P>) -> HashSet<PathBuf> {
let mut top_level_names: HashSet<PathBuf> = HashSet::with_capacity(filenames.len()); let mut top_level_names: HashSet<PathBuf> = HashSet::with_capacity(filenames.len());
let mut to_remove: Vec<PathBuf> = Vec::with_capacity(filenames.len());
for t in filenames { for t in filenames {
let top_level_name = normalize_path(t); let top_level_name = normalize_path(t);
let mut can_add = true; let mut can_add = true;
let mut to_remove: Vec<PathBuf> = Vec::new();
for tt in top_level_names.iter() { for tt in top_level_names.iter() {
if is_a_parent_of(&top_level_name, tt) { if is_a_parent_of(&top_level_name, tt) {
@@ -19,13 +20,14 @@ pub fn simplify_dir_names<P: AsRef<Path>>(filenames: Vec<P>) -> HashSet<PathBuf>
can_add = false; can_add = false;
} }
} }
for r in to_remove { to_remove.sort_unstable();
top_level_names.remove(&r); top_level_names.retain(|tr| to_remove.binary_search(tr).is_err());
} to_remove.clear();
if can_add { if can_add {
top_level_names.insert(top_level_name); top_level_names.insert(top_level_name);
} }
} }
top_level_names top_level_names
} }
@@ -55,20 +57,18 @@ pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
path.as_ref().components().collect::<PathBuf>() path.as_ref().components().collect::<PathBuf>()
} }
pub fn is_filtered_out_due_to_regex(filter_regex: &[Regex], dir: &Path) -> bool { pub fn is_filtered_out_due_to_regex(filter_regex: &Option<Regex>, dir: &Path) -> bool {
if filter_regex.is_empty() { match filter_regex {
false Some(fr) => !fr.is_match(&dir.as_os_str().to_string_lossy()),
} else { None => false,
filter_regex
.iter()
.all(|f| !f.is_match(&dir.as_os_str().to_string_lossy()))
} }
} }
pub fn is_filtered_out_due_to_invert_regex(filter_regex: &[Regex], dir: &Path) -> bool { pub fn is_filtered_out_due_to_invert_regex(filter_regex: &Option<Regex>, dir: &Path) -> bool {
filter_regex match filter_regex {
.iter() Some(fr) => fr.is_match(&dir.as_os_str().to_string_lossy()),
.any(|f| f.is_match(&dir.as_os_str().to_string_lossy())) None => false,
}
} }
fn is_a_parent_of<P: AsRef<Path>>(parent: P, child: P) -> bool { fn is_a_parent_of<P: AsRef<Path>>(parent: P, child: P) -> bool {
@@ -92,7 +92,6 @@ mod tests {
fn test_simplify_dir_rm_subdir() { fn test_simplify_dir_rm_subdir() {
let mut correct = HashSet::new(); let mut correct = HashSet::new();
correct.insert(["a", "b"].iter().collect::<PathBuf>()); correct.insert(["a", "b"].iter().collect::<PathBuf>());
assert_eq!(simplify_dir_names(vec!["a/b/c", "a/b", "a/b/d/f"]), correct);
assert_eq!(simplify_dir_names(vec!["a/b", "a/b/c", "a/b/d/f"]), correct); assert_eq!(simplify_dir_names(vec!["a/b", "a/b/c", "a/b/d/f"]), correct);
} }
+4 -21
View File
@@ -5,6 +5,8 @@ use std::sync::Once;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
mod tests_symlinks;
/** /**
* This file contains tests that verify the exact output of the command. * This file contains tests that verify the exact output of the command.
* This output differs on Linux / Mac so the tests are harder to write and debug * This output differs on Linux / Mac so the tests are harder to write and debug
@@ -139,7 +141,7 @@ pub fn test_substring_of_names_and_long_names() {
fn no_substring_of_names_output() -> Vec<String> { fn no_substring_of_names_output() -> Vec<String> {
let ubuntu = " let ubuntu = "
0B ┌── long_dir_name_what_a_very_long_dir_name_what_happens_when_this_goe.. 0B ┌── long_dir_name_what_a_very_long_dir_name_what_happens_when_this_g..
4.0K ├── dir_name_clash 4.0K ├── dir_name_clash
4.0K │ ┌── hello 4.0K │ ┌── hello
8.0K ├─┴ dir 8.0K ├─┴ dir
@@ -151,7 +153,7 @@ fn no_substring_of_names_output() -> Vec<String> {
.into(); .into();
let mac_and_some_linux = " let mac_and_some_linux = "
0B ┌── long_dir_name_what_a_very_long_dir_name_what_happens_when_this_goe.. 0B ┌── long_dir_name_what_a_very_long_dir_name_what_happens_when_this_g..
4.0K │ ┌── hello 4.0K │ ┌── hello
4.0K ├─┴ dir 4.0K ├─┴ dir
4.0K ├── dir_name_clash 4.0K ├── dir_name_clash
@@ -190,22 +192,3 @@ fn unicode_dir() -> Vec<String> {
.into(); .into();
vec![mac_and_some_linux, ubuntu] vec![mac_and_some_linux, ubuntu]
} }
#[cfg_attr(target_os = "windows", ignore)]
#[test]
pub fn test_apparent_size() {
let command_args = vec!["-c", "-s", "-b", "/tmp/test_dir"];
exact_output_test(apparent_size_output(), command_args);
}
fn apparent_size_output() -> Vec<String> {
// The apparent directory sizes are too unpredictable and system dependant to try and match
let files = r#"
0B ┌── a_file
6B ├── hello_file
"#
.trim()
.to_string();
vec![files]
}
+17 -40
View File
@@ -101,6 +101,22 @@ pub fn test_number_of_files() {
assert!(output.contains("2 ┌─┴ test_dir")); assert!(output.contains("2 ┌─┴ test_dir"));
} }
#[cfg_attr(target_os = "windows", ignore)]
#[test]
pub fn test_apparent_size() {
// Check the '-s' Flag gives us byte sizes and that it doesn't round up to a block
let command_args = vec!["-c", "-s", "/tmp/test_dir"];
let output = build_command(command_args);
let apparent_size1 = "6B ├── hello_file│";
let apparent_size2 = "0B ┌── a_file";
assert!(output.contains(apparent_size1));
assert!(output.contains(apparent_size2));
let incorrect_apparent_size = "4.0K ├── hello_file";
assert!(!output.contains(incorrect_apparent_size));
}
#[test] #[test]
pub fn test_show_files_by_type() { pub fn test_show_files_by_type() {
// Check we can list files by type // Check we can list files by type
@@ -113,38 +129,18 @@ pub fn test_show_files_by_type() {
} }
#[test] #[test]
pub fn test_show_files_by_regex_match_lots() { pub fn test_show_files_by_regex() {
// Check we can see '.rs' files in the tests directory // Check we can see '.rs' files in the tests directory
let output = build_command(vec!["-c", "-e", "\\.rs$", "tests"]); let output = build_command(vec!["-c", "-e", "\\.rs$", "tests"]);
assert!(output.contains(" ┌─┴ tests")); assert!(output.contains(" ┌─┴ tests"));
assert!(!output.contains("0B ┌── tests")); assert!(!output.contains("0B ┌── tests"));
assert!(!output.contains("0B ┌─┴ tests")); assert!(!output.contains("0B ┌─┴ tests"));
}
#[test]
pub fn test_show_files_by_regex_match_nothing() {
// Check there are no files named: '.match_nothing' in the tests directory // Check there are no files named: '.match_nothing' in the tests directory
let output = build_command(vec!["-c", "-e", "match_nothing$", "tests"]); let output = build_command(vec!["-c", "-e", "match_nothing$", "tests"]);
assert!(output.contains("0B ┌── tests")); assert!(output.contains("0B ┌── tests"));
} }
#[test]
pub fn test_show_files_by_regex_match_multiple() {
let output = build_command(vec![
"-c",
"-e",
"test_dir_hidden",
"-e",
"test_dir2",
"-n",
"100",
"tests",
]);
assert!(output.contains("test_dir2"));
assert!(output.contains("test_dir_hidden"));
assert!(!output.contains("many")); // We do not find the 'many' folder in the 'test_dir' folder
}
#[test] #[test]
pub fn test_show_files_by_invert_regex() { pub fn test_show_files_by_invert_regex() {
let output = build_command(vec!["-c", "-f", "-v", "e", "tests/test_dir2"]); let output = build_command(vec!["-c", "-f", "-v", "e", "tests/test_dir2"]);
@@ -159,22 +155,3 @@ pub fn test_show_files_by_invert_regex() {
let output = build_command(vec!["-c", "-f", "-v", "match_nothing$", "tests/test_dir2"]); let output = build_command(vec!["-c", "-f", "-v", "match_nothing$", "tests/test_dir2"]);
assert!(output.contains("4 ┌─┴ test_dir2")); assert!(output.contains("4 ┌─┴ test_dir2"));
} }
#[test]
pub fn test_show_files_by_invert_regex_match_multiple() {
// We ignore test_dir2 & test_dir_unicode, leaving the test_dir folder
// which has the 'many' folder inside
let output = build_command(vec![
"-c",
"-v",
"test_dir2",
"-v",
"test_dir_unicode",
"-n",
"100",
"tests",
]);
assert!(!output.contains("test_dir2"));
assert!(!output.contains("test_dir_unicode"));
assert!(output.contains("many"));
}
+1 -1
View File
@@ -24,7 +24,7 @@ fn get_width_of_terminal() -> u16 {
// Mac test runners create tmp files with very long names, hence it may be shortened in the output // Mac test runners create tmp files with very long names, hence it may be shortened in the output
fn get_file_name(name: String) -> String { fn get_file_name(name: String) -> String {
let terminal_plus_buffer = (get_width_of_terminal() - 12) as usize; let terminal_plus_buffer = (get_width_of_terminal() - 14) as usize;
if UnicodeWidthStr::width(&*name) > terminal_plus_buffer { if UnicodeWidthStr::width(&*name) > terminal_plus_buffer {
let trimmed_name = name let trimmed_name = name
.chars() .chars()