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 133 additions and 80 deletions
+4 -4
View File
@@ -82,11 +82,11 @@ jobs:
job: job:
# { os, target, cargo-options, features, use-cross, toolchain } # { os, target, cargo-options, features, use-cross, toolchain }
- { 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-18.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-18.04 , target: i686-unknown-linux-musl , 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-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: macos-latest , target: x86_64-apple-darwin }
- { os: windows-latest , target: i686-pc-windows-gnu } - { os: windows-latest , target: i686-pc-windows-gnu }
- { os: windows-latest , target: i686-pc-windows-msvc } - { os: windows-latest , target: i686-pc-windows-msvc }
Generated
+23 -14
View File
@@ -31,9 +31,9 @@ dependencies = [
[[package]] [[package]]
name = "assert_cmd" name = "assert_cmd"
version = "1.0.5" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88b6bd5df287567ffdf4ddf4d33060048e1068308e5f62d81c6f9824a045a48" checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f"
dependencies = [ dependencies = [
"bstr", "bstr",
"doc-comment", "doc-comment",
@@ -144,10 +144,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "difference" name = "difflib"
version = "2.0.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]] [[package]]
name = "doc-comment" name = "doc-comment"
@@ -157,13 +157,12 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "du-dust" name = "du-dust"
version = "0.6.0" version = "0.6.1"
dependencies = [ dependencies = [
"ansi_term 0.12.1", "ansi_term 0.12.1",
"assert_cmd", "assert_cmd",
"clap", "clap",
"lscolors", "lscolors",
"num_cpus",
"rayon", "rayon",
"stfu8", "stfu8",
"tempfile", "tempfile",
@@ -192,13 +191,22 @@ dependencies = [
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.18" version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "itertools"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [
"either",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -207,9 +215,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.97" version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]] [[package]]
name = "lscolors" name = "lscolors"
@@ -253,11 +261,12 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]] [[package]]
name = "predicates" name = "predicates"
version = "1.0.8" version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df" checksum = "c6e46ca79eb4e21e2ec14430340c71250ab69332abf85521c95d3a8bc336aa76"
dependencies = [ dependencies = [
"difference", "difflib",
"itertools",
"predicates-core", "predicates-core",
] ]
+1 -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.6.0" version = "0.6.1"
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"] authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
edition = "2018" edition = "2018"
@@ -24,7 +24,6 @@ path = "src/main.rs"
ansi_term = "0.12" ansi_term = "0.12"
clap = { version = "=2.33", features = ["wrap_help"] } clap = { version = "=2.33", features = ["wrap_help"] }
lscolors = "0.7" lscolors = "0.7"
num_cpus = "1"
terminal_size = "0.1" terminal_size = "0.1"
unicode-width = "0.1" unicode-width = "0.1"
rayon="1" rayon="1"
+11 -7
View File
@@ -44,13 +44,17 @@ Dust will list a slightly-less-than-the-terminal-height number of the biggest su
Usage: dust Usage: dust
Usage: dust <dir> Usage: dust <dir>
Usage: dust <dir> <another_dir> <and_more> Usage: dust <dir> <another_dir> <and_more>
Usage: dust -p <dir> (full-path - does not shorten the path of the subdirectories) Usage: dust -p (full-path - Show fullpath 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 -s (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 -n 30 (shows 30 directories instead of the default [default is terminal height])
Usage: dust -d 3 <dir> (shows 3 levels of subdirectories) Usage: dust -d 3 (shows 3 levels of subdirectories)
Usage: dust -r <dir> (reverse order of output, with root at the lowest) Usage: dust -r (reverse order of output)
Usage: dust -X ignore <dir> (ignore all files and directories with the name 'ignore') Usage: dust -X ignore (ignore all files and directories with the name 'ignore')
Usage: dust -b <dir> (do not show percentages or draw ASCII bars) 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)
``` ```
+1 -1
View File
@@ -1,6 +1,6 @@
# ----------- To do a release --------- # ----------- To do a release ---------
# edit version in cargo.toml # 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 tag v0.4.5
# git push origin v0.4.5 # git push origin v0.4.5
+40 -44
View File
@@ -13,30 +13,27 @@ use std::collections::HashSet;
use crate::node::build_node; use crate::node::build_node;
use std::fs::DirEntry; use std::fs::DirEntry;
pub fn walk_it( use crate::platform::get_metadata;
dirs: HashSet<PathBuf>,
ignore_directories: HashSet<PathBuf>, pub struct WalkData {
use_apparent_size: bool, pub ignore_directories: HashSet<PathBuf>,
by_filecount: bool, pub allowed_filesystems: HashSet<u64>,
ignore_hidden: bool, pub use_apparent_size: bool,
) -> (Vec<Node>, 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 permissions_flag = AtomicBool::new(false);
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( let n = walk(d, &permissions_flag, &walk_data);
d,
&permissions_flag,
&ignore_directories,
use_apparent_size,
by_filecount,
ignore_hidden,
);
match n { match n {
Some(n) => { Some(n) => {
let mut inodes: HashSet<(u64, u64)> = HashSet::new(); 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, None => None,
} }
@@ -74,24 +71,23 @@ fn clean_inodes(
}); });
} }
fn ignore_file( fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
entry: &DirEntry,
ignore_hidden: bool,
ignore_directories: &HashSet<PathBuf>,
) -> bool {
let is_dot_file = entry.file_name().to_str().unwrap_or("").starts_with('.'); let is_dot_file = entry.file_name().to_str().unwrap_or("").starts_with('.');
let is_ignored_path = ignore_directories.contains(&entry.path()); let is_ignored_path = walk_data.ignore_directories.contains(&entry.path());
(is_dot_file && ignore_hidden) || is_ignored_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( fn walk(dir: PathBuf, permissions_flag: &AtomicBool, walk_data: &WalkData) -> Option<Node> {
dir: PathBuf,
permissions_flag: &AtomicBool,
ignore_directories: &HashSet<PathBuf>,
use_apparent_size: bool,
by_filecount: bool,
ignore_hidden: bool,
) -> 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()) {
@@ -104,25 +100,19 @@ fn walk(
// rayon doesn't parallelise as well giving a 3X performance drop // rayon doesn't parallelise as well giving a 3X performance drop
// hence we unravel the recursion a bit // 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 let Ok(data) = entry.file_type() {
if data.is_dir() && !data.is_symlink() { if data.is_dir() && !data.is_symlink() {
return walk( return walk(entry.path(), permissions_flag, walk_data);
entry.path(),
permissions_flag,
ignore_directories,
use_apparent_size,
by_filecount,
ignore_hidden,
);
} }
return build_node( return build_node(
entry.path(), entry.path(),
vec![], vec![],
use_apparent_size, walk_data.use_apparent_size,
by_filecount, data.is_symlink(),
walk_data.by_filecount,
); );
} }
} }
@@ -135,7 +125,13 @@ fn walk(
} else { } else {
permissions_flag.store(true, atomic::Ordering::Relaxed); 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 { mod tests {
+25 -7
View File
@@ -7,14 +7,16 @@ use std::collections::HashSet;
use self::display::draw_it; use self::display::draw_it;
use clap::{App, AppSettings, Arg}; 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 filter::{get_biggest, get_by_depth};
use std::cmp::max; use std::cmp::max;
use std::path::PathBuf; use std::path::PathBuf;
use terminal_size::{terminal_size, Height, Width}; use terminal_size::{terminal_size, Height, Width};
use utils::get_filesystem_devices;
use utils::simplify_dir_names; use utils::simplify_dir_names;
mod dirwalker; mod dir_walker;
mod display; mod display;
mod display_node; mod display_node;
mod filter; mod filter;
@@ -107,6 +109,12 @@ fn main() {
.multiple(true) .multiple(true)
.help("Exclude any file or directory with this name"), .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(
Arg::with_name("display_apparent_size") Arg::with_name("display_apparent_size")
.short("s") .short("s")
@@ -141,7 +149,7 @@ fn main() {
Arg::with_name("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")
.help("Obey .git_ignore rules & Do not display hidden files"), .help("Do not display hidden files"),
) )
.arg( .arg(
Arg::with_name("width") Arg::with_name("width")
@@ -191,21 +199,31 @@ fn main() {
let by_filecount = options.is_present("by_filecount"); let by_filecount = options.is_present("by_filecount");
let ignore_hidden = options.is_present("ignore_hidden"); 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 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 let ignored_full_path: HashSet<PathBuf> = ignore_directories
.into_iter() .into_iter()
.flat_map(|x| simplified_dirs.iter().map(move |d| d.join(x.clone()))) .flat_map(|x| simplified_dirs.iter().map(move |d| d.join(x.clone())))
.collect(); .collect();
let (nodes, errors) = walk_it( let walk_data = WalkData {
simplified_dirs, ignore_directories: ignored_full_path,
ignored_full_path, allowed_filesystems,
use_apparent_size, use_apparent_size,
by_filecount, by_filecount,
ignore_hidden, ignore_hidden,
); };
let (nodes, errors) = walk_it(simplified_dirs, walk_data);
let tree = { let tree = {
match depth { match depth {
+9 -1
View File
@@ -15,11 +15,19 @@ pub fn build_node(
dir: PathBuf, dir: PathBuf,
children: Vec<Node>, children: Vec<Node>,
use_apparent_size: bool, use_apparent_size: bool,
is_symlink: bool,
by_filecount: bool, by_filecount: bool,
) -> Option<Node> { ) -> Option<Node> {
match get_metadata(&dir, use_apparent_size) { match get_metadata(&dir, use_apparent_size) {
Some(data) => { 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 { Some(Node {
name: dir, name: dir,
size, size,
+19
View File
@@ -1,6 +1,9 @@
use platform::get_metadata;
use std::collections::HashSet; use std::collections::HashSet;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::platform;
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 {
let parent = parent.as_ref(); let parent = parent.as_ref();
let child = child.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 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 { pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
// normalize path ... // normalize path ...
// 1. removing repeated separators // 1. removing repeated separators