Compare commits

...

12 Commits

Author SHA1 Message Date
andy.boot
8fddb24165 Increment version 2021-07-19 14:09:21 +01:00
andy.boot
ed3902f07e Rename file: dirwalker -> dir_walker
Felt like this file was missing an '_'
2021-07-16 14:13:12 +01:00
andy.boot
f219a752d6 Refactor: Compress arguemnts to one object
Several arguments were passed around the dirwalker file. Compress them
into a single struct.
2021-07-16 14:13:12 +01:00
andy.boot
f6e36aba52 Feature: Re-introduce -x flag to limit filesystem
-x flag allows dust to limit itself to the current filesystem
2021-07-16 14:13:12 +01:00
andy.boot
c286b8ba97 Revert "README: Remove -x option"
This reverts commit 1d062cf683.
2021-07-16 14:13:12 +01:00
andy.boot
3dad7abfb8 Change size of softlinks to 0
Instead of the size of what they point at
2021-07-16 14:13:12 +01:00
andy.boot
42163abb73 Cargo: Remove num_cpus library. Ran update
Not needed since v0.6.0
Ran cargo update
2021-07-07 18:35:05 +01:00
andy.boot
8e0188c755 README: Update usage examples of dust 2021-07-07 18:35:05 +01:00
andy.boot
555d86206d ci: update versions of ubuntu 2021-06-23 10:05:48 +01:00
andy.boot
02392881c5 Update version 2021-06-23 09:40:58 +01:00
andy.boot
6f1175ef8d README: Add another tool to list of alternatives 2021-06-23 09:40:58 +01:00
andy.boot
1d062cf683 README: Remove -x option
This behaviour was removed in previous commit
2021-06-23 09:40:58 +01:00
9 changed files with 136 additions and 81 deletions

View File

@@ -82,11 +82,11 @@ jobs:
job:
# { os, target, cargo-options, features, use-cross, toolchain }
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , use-cross: use-cross }
- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , use-cross: use-cross }
- { os: ubuntu-18.04 , target: i686-unknown-linux-musl , 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: x86_64-unknown-linux-gnu , use-cross: use-cross }
- { os: ubuntu-20.04 , target: x86_64-unknown-linux-musl , use-cross: use-cross }
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-gnu , use-cross: use-cross }
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-musl , use-cross: use-cross }
- { os: ubuntu-16.04 , target: x86_64-unknown-linux-gnu , use-cross: use-cross }
- { os: macos-latest , target: x86_64-apple-darwin }
- { os: windows-latest , target: i686-pc-windows-gnu }
- { os: windows-latest , target: i686-pc-windows-msvc }

39
Cargo.lock generated
View File

@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
@@ -29,9 +31,9 @@ dependencies = [
[[package]]
name = "assert_cmd"
version = "1.0.5"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88b6bd5df287567ffdf4ddf4d33060048e1068308e5f62d81c6f9824a045a48"
checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f"
dependencies = [
"bstr",
"doc-comment",
@@ -142,10 +144,10 @@ dependencies = [
]
[[package]]
name = "difference"
version = "2.0.0"
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "doc-comment"
@@ -155,13 +157,12 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "du-dust"
version = "0.5.4"
version = "0.6.1"
dependencies = [
"ansi_term 0.12.1",
"assert_cmd",
"clap",
"lscolors",
"num_cpus",
"rayon",
"stfu8",
"tempfile",
@@ -190,13 +191,22 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [
"either",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -205,9 +215,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.97"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "lscolors"
@@ -251,11 +261,12 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "predicates"
version = "1.0.8"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df"
checksum = "c6e46ca79eb4e21e2ec14430340c71250ab69332abf85521c95d3a8bc336aa76"
dependencies = [
"difference",
"difflib",
"itertools",
"predicates-core",
]

View File

@@ -1,7 +1,7 @@
[package]
name = "du-dust"
description = "A more intuitive version of du"
version = "0.5.4"
version = "0.6.1"
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
edition = "2018"
@@ -24,7 +24,6 @@ path = "src/main.rs"
ansi_term = "0.12"
clap = { version = "=2.33", features = ["wrap_help"] }
lscolors = "0.7"
num_cpus = "1"
terminal_size = "0.1"
unicode-width = "0.1"
rayon="1"

View File

@@ -44,14 +44,17 @@ Dust will list a slightly-less-than-the-terminal-height number of the biggest su
Usage: dust
Usage: dust <dir>
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 instead of the default)
Usage: dust -d 3 <dir> (shows 3 levels of subdirectories)
Usage: dust -r <dir> (reverse order of output, with root at the lowest)
Usage: dust -x <dir> (only show directories on the same filesystem)
Usage: dust -X ignore <dir> (ignore all files and directories with the name 'ignore')
Usage: dust -b <dir> (do not show percentages or draw ASCII bars)
Usage: dust -p (full-path - Show fullpath of the subdirectories)
Usage: dust -s (apparent-size - shows the length of the file as opposed to the amount of disk space it uses)
Usage: dust -n 30 (shows 30 directories instead of the default [default is terminal height])
Usage: dust -d 3 (shows 3 levels of subdirectories)
Usage: dust -r (reverse order of output)
Usage: dust -X ignore (ignore all files and directories with the name 'ignore')
Usage: dust -x (only show directories on the same filesystem)
Usage: dust -b (do not show percentages or draw ASCII bars)
Usage: dust -i (do not show hidden files)
Usage: dust -c (No colors [monochrome])
Usage: dust -f (Count files instead of diskspace)
```
@@ -61,6 +64,7 @@ Usage: dust -b <dir> (do not show percentages or draw ASCII bars)
* [dutree](https://github.com/nachoparker/dutree)
* [dua](https://github.com/Byron/dua-cli/)
* [pdu](https://github.com/KSXGitHub/parallel-disk-usage)
* [dirstat-rs](https://github.com/scullionw/dirstat-rs)
* 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.

View File

@@ -1,6 +1,6 @@
# ----------- To do a release ---------
# edit version in cargo.toml
# tag a commit and push (increment version first):
# tag a commit and push (increment version in Cargo.toml first):
# git tag v0.4.5
# git push origin v0.4.5

View File

@@ -13,30 +13,27 @@ use std::collections::HashSet;
use crate::node::build_node;
use std::fs::DirEntry;
pub fn walk_it(
dirs: HashSet<PathBuf>,
ignore_directories: HashSet<PathBuf>,
use_apparent_size: bool,
by_filecount: bool,
ignore_hidden: bool,
) -> (Vec<Node>, bool) {
use crate::platform::get_metadata;
pub struct WalkData {
pub ignore_directories: HashSet<PathBuf>,
pub allowed_filesystems: HashSet<u64>,
pub use_apparent_size: bool,
pub by_filecount: bool,
pub ignore_hidden: bool,
}
pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: WalkData) -> (Vec<Node>, bool) {
let permissions_flag = AtomicBool::new(false);
let top_level_nodes: Vec<_> = dirs
.into_iter()
.filter_map(|d| {
let n = walk(
d,
&permissions_flag,
&ignore_directories,
use_apparent_size,
by_filecount,
ignore_hidden,
);
let n = walk(d, &permissions_flag, &walk_data);
match n {
Some(n) => {
let mut inodes: HashSet<(u64, u64)> = HashSet::new();
clean_inodes(n, &mut inodes, use_apparent_size)
clean_inodes(n, &mut inodes, walk_data.use_apparent_size)
}
None => None,
}
@@ -74,24 +71,23 @@ fn clean_inodes(
});
}
fn ignore_file(
entry: &DirEntry,
ignore_hidden: bool,
ignore_directories: &HashSet<PathBuf>,
) -> bool {
fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
let is_dot_file = entry.file_name().to_str().unwrap_or("").starts_with('.');
let is_ignored_path = ignore_directories.contains(&entry.path());
(is_dot_file && ignore_hidden) || is_ignored_path
let is_ignored_path = walk_data.ignore_directories.contains(&entry.path());
if !walk_data.allowed_filesystems.is_empty() {
let size_inode_device = get_metadata(&entry.path(), false);
if let Some((_size, Some((_id, dev)))) = size_inode_device {
if !walk_data.allowed_filesystems.contains(&dev) {
return true;
}
}
}
(is_dot_file && walk_data.ignore_hidden) || is_ignored_path
}
fn walk(
dir: PathBuf,
permissions_flag: &AtomicBool,
ignore_directories: &HashSet<PathBuf>,
use_apparent_size: bool,
by_filecount: bool,
ignore_hidden: bool,
) -> Option<Node> {
fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Option<Node> {
let mut children = vec![];
if let Ok(entries) = fs::read_dir(dir.clone()) {
@@ -104,25 +100,19 @@ fn walk(
// rayon doesn't parallelise as well giving a 3X performance drop
// hence we unravel the recursion a bit
// return walk(entry.path(), permissions_flag, ignore_directories, use_apparent_size, by_filecount, ignore_hidden);
// return walk(entry.path(), permissions_flag, ignore_directories, allowed_filesystems, use_apparent_size, by_filecount, ignore_hidden);
if !ignore_file(&entry, ignore_hidden, &ignore_directories) {
if !ignore_file(&entry, walk_data) {
if let Ok(data) = entry.file_type() {
if data.is_dir() && !data.is_symlink() {
return walk(
entry.path(),
permissions_flag,
ignore_directories,
use_apparent_size,
by_filecount,
ignore_hidden,
);
return walk(entry.path(), permissions_flag, walk_data);
}
return build_node(
entry.path(),
vec![],
use_apparent_size,
by_filecount,
walk_data.use_apparent_size,
data.is_symlink(),
walk_data.by_filecount,
);
}
}
@@ -135,7 +125,13 @@ fn walk(
} else {
permissions_flag.store(true, atomic::Ordering::Relaxed);
}
build_node(dir, children, use_apparent_size, by_filecount)
build_node(
dir,
children,
walk_data.use_apparent_size,
false,
walk_data.by_filecount,
)
}
mod tests {

View File

@@ -7,14 +7,16 @@ use std::collections::HashSet;
use self::display::draw_it;
use clap::{App, AppSettings, Arg};
use dirwalker::walk_it;
use dir_walker::walk_it;
use dir_walker::WalkData;
use filter::{get_biggest, get_by_depth};
use std::cmp::max;
use std::path::PathBuf;
use terminal_size::{terminal_size, Height, Width};
use utils::get_filesystem_devices;
use utils::simplify_dir_names;
mod dirwalker;
mod dir_walker;
mod display;
mod display_node;
mod filter;
@@ -107,6 +109,12 @@ fn main() {
.multiple(true)
.help("Exclude any file or directory with this name"),
)
.arg(
Arg::with_name("limit_filesystem")
.short("x")
.long("limit-filesystem")
.help("Only count the files and directories on the same filesystem as the supplied directory"),
)
.arg(
Arg::with_name("display_apparent_size")
.short("s")
@@ -141,7 +149,7 @@ fn main() {
Arg::with_name("ignore_hidden")
.short("i") // Do not use 'h' this is used by 'help'
.long("ignore_hidden")
.help("Obey .git_ignore rules & Do not display hidden files"),
.help("Do not display hidden files"),
)
.arg(
Arg::with_name("width")
@@ -191,21 +199,31 @@ fn main() {
let by_filecount = options.is_present("by_filecount");
let ignore_hidden = options.is_present("ignore_hidden");
let limit_filesystem = options.is_present("limit_filesystem");
let simplified_dirs = simplify_dir_names(target_dirs);
let allowed_filesystems = {
if limit_filesystem {
get_filesystem_devices(simplified_dirs.iter())
} else {
HashSet::new()
}
};
let ignored_full_path: HashSet<PathBuf> = ignore_directories
.into_iter()
.flat_map(|x| simplified_dirs.iter().map(move |d| d.join(x.clone())))
.collect();
let (nodes, errors) = walk_it(
simplified_dirs,
ignored_full_path,
let walk_data = WalkData {
ignore_directories: ignored_full_path,
allowed_filesystems,
use_apparent_size,
by_filecount,
ignore_hidden,
);
};
let (nodes, errors) = walk_it(simplified_dirs, walk_data);
let tree = {
match depth {

View File

@@ -15,11 +15,19 @@ pub fn build_node(
dir: PathBuf,
children: Vec<Node>,
use_apparent_size: bool,
is_symlink: bool,
by_filecount: bool,
) -> Option<Node> {
match get_metadata(&dir, use_apparent_size) {
Some(data) => {
let (size, inode_device) = if by_filecount { (1, data.1) } else { data };
let (size, inode_device) = if by_filecount {
(1, data.1)
} else if is_symlink && !use_apparent_size {
(0, None)
} else {
data
};
Some(Node {
name: dir,
size,

View File

@@ -1,6 +1,9 @@
use platform::get_metadata;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use crate::platform;
fn is_a_parent_of<P: AsRef<Path>>(parent: P, child: P) -> bool {
let parent = parent.as_ref();
let child = child.as_ref();
@@ -33,6 +36,22 @@ pub fn simplify_dir_names<P: AsRef<Path>>(filenames: Vec<P>) -> HashSet<PathBuf>
top_level_names
}
pub fn get_filesystem_devices<'a, P: IntoIterator<Item = &'a PathBuf>>(paths: P) -> HashSet<u64> {
// Gets the device ids for the filesystems which are used by the argument paths
paths
.into_iter()
.filter_map(|p| {
let meta = get_metadata(&p, false);
if let Some((_size, Some((_id, dev)))) = meta {
Some(dev)
} else {
None
}
})
.collect()
}
pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
// normalize path ...
// 1. removing repeated separators