Compare commits

..

2 Commits

Author SHA1 Message Date
andy.boot 403f78644c Testing releases 2022-02-27 09:49:05 +00:00
Adam Stephens 2c6aaa4c41 add aarch64 gnu and musl cross targets 2022-02-26 21:12:17 -05:00
10 changed files with 85 additions and 72 deletions
Generated
+3 -3
View File
@@ -148,7 +148,7 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "du-dust"
version = "0.8.1"
version = "0.8.0"
dependencies = [
"ansi_term",
"assert_cmd",
@@ -340,9 +340,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.5.5"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "du-dust"
description = "A more intuitive version of du"
version = "0.8.1"
version = "0.8.1-alpha.1"
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
edition = "2018"
readme = "README.md"
+1 -1
View File
@@ -32,7 +32,7 @@ Because I want an easy way to see where my disk is being used.
#### 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)
* Windows MSVC - requires: VCRUNTIME140.dll
#### Download
+1
View File
@@ -3,6 +3,7 @@
# tag a commit and push (increment version in Cargo.toml first):
# git tag v0.4.5
# git push origin v0.4.5
# pre release notation: "0.8.1-alpha.1"
# cargo publish to put it in crates.io
+3 -12
View File
@@ -34,7 +34,7 @@ pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: WalkData) -> (Vec<Node>, bool)
let top_level_nodes: Vec<_> = dirs
.into_iter()
.filter_map(|d| {
let n = walk(d, &permissions_flag, &walk_data, 0);
let n = walk(d, &permissions_flag, &walk_data);
match n {
Some(n) => {
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>(),
children: new_children,
inode_device: x.inode_device,
depth: x.depth,
});
}
@@ -109,12 +108,7 @@ fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
(is_dot_file && walk_data.ignore_hidden) || is_ignored_path
}
fn walk(
dir: PathBuf,
permissions_flag: &AtomicBool,
walk_data: &WalkData,
depth: usize,
) -> 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()) {
@@ -132,7 +126,7 @@ fn walk(
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, walk_data, depth + 1);
return walk(entry.path(), permissions_flag, walk_data);
}
return build_node(
entry.path(),
@@ -143,7 +137,6 @@ fn walk(
data.is_symlink(),
data.is_file(),
walk_data.by_filecount,
depth,
);
}
}
@@ -165,7 +158,6 @@ fn walk(
false,
false,
walk_data.by_filecount,
depth,
)
}
@@ -180,7 +172,6 @@ mod tests {
size: 10,
children: vec![],
inode_device: Some((5, 6)),
depth: 0,
}
}
+37 -10
View File
@@ -5,10 +5,18 @@ use std::collections::HashMap;
use std::collections::HashSet;
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(
top_level_nodes: Vec<Node>,
n: usize,
depth: usize,
using_a_filter: bool,
) -> Option<DisplayNode> {
if top_level_nodes.is_empty() {
@@ -22,14 +30,14 @@ pub fn get_biggest(
let mut allowed_nodes = HashSet::new();
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 {
let line = heap.pop();
match line {
Some(line) => {
allowed_nodes.insert(&line.name);
heap = add_children(using_a_filter, line, depth, heap);
heap = add_children(using_a_filter, line, heap);
}
None => break,
}
@@ -69,20 +77,17 @@ pub fn get_all_file_types(top_level_nodes: Vec<Node>, n: usize) -> Option<Displa
fn add_children<'a>(
using_a_filter: bool,
file_or_folder: &'a Node,
depth: usize,
line: &'a Node,
mut heap: BinaryHeap<&'a Node>,
) -> BinaryHeap<&'a Node> {
if depth > file_or_folder.depth {
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 {
heap.push(c)
}
});
} else {
file_or_folder.children.iter().for_each(|c| heap.push(c));
}
line.children.iter().for_each(|c| heap.push(c));
}
heap
}
@@ -106,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 {
if top_level_nodes.len() > 1 {
let total_size = top_level_nodes.iter().map(|node| node.size).sum();
@@ -114,7 +142,6 @@ fn get_new_root(top_level_nodes: Vec<Node>) -> Node {
size: total_size,
children: top_level_nodes,
inode_device: None,
depth: 0,
}
} else {
top_level_nodes.into_iter().next().unwrap()
+25 -29
View File
@@ -10,7 +10,7 @@ use self::display::draw_it;
use clap::{crate_version, Arg};
use clap::{Command, Values};
use dir_walker::{walk_it, WalkData};
use filter::{get_all_file_types, get_biggest};
use filter::{get_all_file_types, get_biggest, get_by_depth};
use regex::Regex;
use std::cmp::max;
use std::path::PathBuf;
@@ -99,6 +99,9 @@ fn get_regex_value(maybe_value: Option<Values>) -> Vec<Regex> {
}
fn main() {
let default_height = get_height_of_terminal();
let def_num_str = default_height.to_string();
let options = Command::new("Dust")
.about("Like du but more intuitive")
.version(crate_version!())
@@ -109,7 +112,7 @@ fn main() {
.long("depth")
.help("Depth to show")
.takes_value(true)
.default_value(usize::MAX.to_string().as_ref())
.conflicts_with("number_of_lines"),
)
.arg(
Arg::new("number_of_lines")
@@ -117,6 +120,7 @@ fn main() {
.long("number-of-lines")
.help("Number of lines of output to show. (Default is terminal_height - 10)")
.takes_value(true)
.default_value(def_num_str.as_ref()),
)
.arg(
Arg::new("display_full_paths")
@@ -184,6 +188,7 @@ fn main() {
.multiple_occurrences(true)
.conflicts_with("filter")
.conflicts_with("types")
.conflicts_with("depth")
.help("Exclude filepaths matching this regex. To ignore png files type: -v \"\\.png$\" "),
)
.arg(
@@ -194,6 +199,7 @@ fn main() {
.number_of_values(1)
.multiple_occurrences(true)
.conflicts_with("types")
.conflicts_with("depth")
.help("Only include filepaths matching this regex. For png files type: -e \"\\.png$\" "),
)
.arg(
@@ -230,36 +236,26 @@ fn main() {
let filter_regexs = get_regex_value(options.values_of("filter"));
let invert_filter_regexs = get_regex_value(options.values_of("invert_filter"));
let number_of_lines = match options.value_of_t("number_of_lines") {
Ok(v) => v,
Err(_) => {
eprintln!("Ignoring bad value for number_of_lines");
default_height
}
};
let terminal_width = match options.value_of_t("width") {
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(_) => {
eprintln!("Ignoring bad value for number_of_lines");
default_height
}
},
None => default_height,
};
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 use_apparent_size = options.is_present("display_apparent_size");
@@ -301,10 +297,10 @@ fn main() {
let tree = {
match (depth, summarize_file_types) {
(_, 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,
number_of_lines,
depth,
options.values_of("filter").is_some()
|| options.value_of("invert_filter").is_some(),
),
-3
View File
@@ -12,7 +12,6 @@ pub struct Node {
pub size: u64,
pub children: Vec<Node>,
pub inode_device: Option<(u64, u64)>,
pub depth: usize,
}
#[allow(clippy::too_many_arguments)]
@@ -25,7 +24,6 @@ pub fn build_node(
is_symlink: bool,
is_file: bool,
by_filecount: bool,
depth: usize,
) -> Option<Node> {
match get_metadata(&dir, use_apparent_size) {
Some(data) => {
@@ -52,7 +50,6 @@ pub fn build_node(
size,
children,
inode_device,
depth,
})
}
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()
& !(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM);
if (attr_filtered & FILE_ATTRIBUTE_ARCHIVE) != 0
|| (attr_filtered & FILE_ATTRIBUTE_DIRECTORY) != 0
if attr_filtered == FILE_ATTRIBUTE_ARCHIVE
|| attr_filtered == FILE_ATTRIBUTE_DIRECTORY
|| md.file_attributes() == FILE_ATTRIBUTE_NORMAL
{
Some((md.len(), None))
+6 -5
View File
@@ -7,10 +7,11 @@ use regex::Regex;
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 to_remove: Vec<PathBuf> = Vec::with_capacity(filenames.len());
for t in filenames {
let top_level_name = normalize_path(t);
let mut can_add = true;
let mut to_remove: Vec<PathBuf> = Vec::new();
for tt in top_level_names.iter() {
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;
}
}
for r in to_remove {
top_level_names.remove(&r);
}
to_remove.sort_unstable();
top_level_names.retain(|tr| to_remove.binary_search(tr).is_err());
to_remove.clear();
if can_add {
top_level_names.insert(top_level_name);
}
}
top_level_names
}
@@ -92,7 +94,6 @@ mod tests {
fn test_simplify_dir_rm_subdir() {
let mut correct = HashSet::new();
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);
}