mirror of
https://github.com/bootandy/dust.git
synced 2026-06-08 11:29:05 +03:00
feat: support Dust tree by age
This commit is contained in:
@@ -44,6 +44,8 @@ _dust() {
|
|||||||
'-y+[just like -mtime, but based on file change time]: : ' \
|
'-y+[just like -mtime, but based on file change time]: : ' \
|
||||||
'--ctime=[just like -mtime, but based on file change time]: : ' \
|
'--ctime=[just like -mtime, but based on file change time]: : ' \
|
||||||
'--files0-from=[run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input]: :_files' \
|
'--files0-from=[run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input]: :_files' \
|
||||||
|
'-m+[Directory '\''size'\'' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time]: :(a c m)' \
|
||||||
|
'--filetime=[Directory '\''size'\'' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time]: :(a c m)' \
|
||||||
'-p[Subdirectories will not have their path shortened]' \
|
'-p[Subdirectories will not have their path shortened]' \
|
||||||
'--full-paths[Subdirectories will not have their path shortened]' \
|
'--full-paths[Subdirectories will not have their path shortened]' \
|
||||||
'-L[dereference sym links - Treat sym links as directories and go into them]' \
|
'-L[dereference sym links - Treat sym links as directories and go into them]' \
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock {
|
|||||||
[CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'just like -mtime, but based on file change time')
|
[CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'just like -mtime, but based on file change time')
|
||||||
[CompletionResult]::new('--ctime', 'ctime', [CompletionResultType]::ParameterName, 'just like -mtime, but based on file change time')
|
[CompletionResult]::new('--ctime', 'ctime', [CompletionResultType]::ParameterName, 'just like -mtime, but based on file change time')
|
||||||
[CompletionResult]::new('--files0-from', 'files0-from', [CompletionResultType]::ParameterName, 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input')
|
[CompletionResult]::new('--files0-from', 'files0-from', [CompletionResultType]::ParameterName, 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input')
|
||||||
|
[CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Directory ''size'' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time')
|
||||||
|
[CompletionResult]::new('--filetime', 'filetime', [CompletionResultType]::ParameterName, 'Directory ''size'' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time')
|
||||||
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
||||||
[CompletionResult]::new('--full-paths', 'full-paths', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
[CompletionResult]::new('--full-paths', 'full-paths', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
||||||
[CompletionResult]::new('-L', 'L ', [CompletionResultType]::ParameterName, 'dereference sym links - Treat sym links as directories and go into them')
|
[CompletionResult]::new('-L', 'L ', [CompletionResultType]::ParameterName, 'dereference sym links - Treat sym links as directories and go into them')
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ _dust() {
|
|||||||
|
|
||||||
case "${cmd}" in
|
case "${cmd}" in
|
||||||
dust)
|
dust)
|
||||||
opts="-d -T -n -p -X -I -L -x -s -r -c -C -b -B -z -R -f -i -v -e -t -w -P -D -F -o -S -j -M -A -y -h -V --depth --threads --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --force-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --no-progress --print-errors --only-dir --only-file --output-format --stack-size --output-json --mtime --atime --ctime --files0-from --help --version [PATH]..."
|
opts="-d -T -n -p -X -I -L -x -s -r -c -C -b -B -z -R -f -i -v -e -t -w -P -D -F -o -S -j -M -A -y -m -h -V --depth --threads --number-of-lines --full-paths --ignore-directory --ignore-all-in-file --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --force-colors --no-percent-bars --bars-on-right --min-size --screen-reader --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --no-progress --print-errors --only-dir --only-file --output-format --stack-size --output-json --mtime --atime --ctime --files0-from --filetime --help --version [PATH]..."
|
||||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
@@ -163,6 +163,14 @@ _dust() {
|
|||||||
COMPREPLY=($(compgen -f "${cur}"))
|
COMPREPLY=($(compgen -f "${cur}"))
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
--filetime)
|
||||||
|
COMPREPLY=($(compgen -W "a c m" -- "${cur}"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-m)
|
||||||
|
COMPREPLY=($(compgen -W "a c m" -- "${cur}"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ set edit:completion:arg-completer[dust] = {|@words|
|
|||||||
cand -y 'just like -mtime, but based on file change time'
|
cand -y 'just like -mtime, but based on file change time'
|
||||||
cand --ctime 'just like -mtime, but based on file change time'
|
cand --ctime 'just like -mtime, but based on file change time'
|
||||||
cand --files0-from 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input'
|
cand --files0-from 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input'
|
||||||
|
cand -m 'Directory ''size'' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time'
|
||||||
|
cand --filetime 'Directory ''size'' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time'
|
||||||
cand -p 'Subdirectories will not have their path shortened'
|
cand -p 'Subdirectories will not have their path shortened'
|
||||||
cand --full-paths 'Subdirectories will not have their path shortened'
|
cand --full-paths 'Subdirectories will not have their path shortened'
|
||||||
cand -L 'dereference sym links - Treat sym links as directories and go into them'
|
cand -L 'dereference sym links - Treat sym links as directories and go into them'
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ complete -c dust -s M -l mtime -d '+/-n matches files modified more/less than n
|
|||||||
complete -c dust -s A -l atime -d 'just like -mtime, but based on file access time' -r
|
complete -c dust -s A -l atime -d 'just like -mtime, but based on file access time' -r
|
||||||
complete -c dust -s y -l ctime -d 'just like -mtime, but based on file change time' -r
|
complete -c dust -s y -l ctime -d 'just like -mtime, but based on file change time' -r
|
||||||
complete -c dust -l files0-from -d 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input' -r -F
|
complete -c dust -l files0-from -d 'run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input' -r -F
|
||||||
|
complete -c dust -s m -l filetime -d 'Directory \'size\' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time' -r -f -a "{a '',c '',m ''}"
|
||||||
complete -c dust -s p -l full-paths -d 'Subdirectories will not have their path shortened'
|
complete -c dust -s p -l full-paths -d 'Subdirectories will not have their path shortened'
|
||||||
complete -c dust -s L -l dereference-links -d 'dereference sym links - Treat sym links as directories and go into them'
|
complete -c dust -s L -l dereference-links -d 'dereference sym links - Treat sym links as directories and go into them'
|
||||||
complete -c dust -s x -l limit-filesystem -d 'Only count the files and directories on the same filesystem as the supplied directory'
|
complete -c dust -s x -l limit-filesystem -d 'Only count the files and directories on the same filesystem as the supplied directory'
|
||||||
|
|||||||
+8
-1
@@ -4,7 +4,7 @@
|
|||||||
.SH NAME
|
.SH NAME
|
||||||
Dust \- Like du but more intuitive
|
Dust \- Like du but more intuitive
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\fBdust\fR [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-T\fR|\fB\-\-threads\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-I\fR|\fB\-\-ignore\-all\-in\-file\fR] [\fB\-L\fR|\fB\-\-dereference\-links\fR] [\fB\-x\fR|\fB\-\-limit\-filesystem\fR] [\fB\-s\fR|\fB\-\-apparent\-size\fR] [\fB\-r\fR|\fB\-\-reverse\fR] [\fB\-c\fR|\fB\-\-no\-colors\fR] [\fB\-C\fR|\fB\-\-force\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-B\fR|\fB\-\-bars\-on\-right\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-R\fR|\fB\-\-screen\-reader\fR] [\fB\-\-skip\-total\fR] [\fB\-f\fR|\fB\-\-filecount\fR] [\fB\-i\fR|\fB\-\-ignore_hidden\fR] [\fB\-v\fR|\fB\-\-invert\-filter\fR] [\fB\-e\fR|\fB\-\-filter\fR] [\fB\-t\fR|\fB\-\-file_types\fR] [\fB\-w\fR|\fB\-\-terminal_width\fR] [\fB\-P\fR|\fB\-\-no\-progress\fR] [\fB\-\-print\-errors\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fB\-o\fR|\fB\-\-output\-format\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-j\fR|\fB\-\-output\-json\fR] [\fB\-M\fR|\fB\-\-mtime\fR] [\fB\-A\fR|\fB\-\-atime\fR] [\fB\-y\fR|\fB\-\-ctime\fR] [\fB\-\-files0\-from\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIPATH\fR]
|
\fBdust\fR [\fB\-d\fR|\fB\-\-depth\fR] [\fB\-T\fR|\fB\-\-threads\fR] [\fB\-n\fR|\fB\-\-number\-of\-lines\fR] [\fB\-p\fR|\fB\-\-full\-paths\fR] [\fB\-X\fR|\fB\-\-ignore\-directory\fR] [\fB\-I\fR|\fB\-\-ignore\-all\-in\-file\fR] [\fB\-L\fR|\fB\-\-dereference\-links\fR] [\fB\-x\fR|\fB\-\-limit\-filesystem\fR] [\fB\-s\fR|\fB\-\-apparent\-size\fR] [\fB\-r\fR|\fB\-\-reverse\fR] [\fB\-c\fR|\fB\-\-no\-colors\fR] [\fB\-C\fR|\fB\-\-force\-colors\fR] [\fB\-b\fR|\fB\-\-no\-percent\-bars\fR] [\fB\-B\fR|\fB\-\-bars\-on\-right\fR] [\fB\-z\fR|\fB\-\-min\-size\fR] [\fB\-R\fR|\fB\-\-screen\-reader\fR] [\fB\-\-skip\-total\fR] [\fB\-f\fR|\fB\-\-filecount\fR] [\fB\-i\fR|\fB\-\-ignore_hidden\fR] [\fB\-v\fR|\fB\-\-invert\-filter\fR] [\fB\-e\fR|\fB\-\-filter\fR] [\fB\-t\fR|\fB\-\-file_types\fR] [\fB\-w\fR|\fB\-\-terminal_width\fR] [\fB\-P\fR|\fB\-\-no\-progress\fR] [\fB\-\-print\-errors\fR] [\fB\-D\fR|\fB\-\-only\-dir\fR] [\fB\-F\fR|\fB\-\-only\-file\fR] [\fB\-o\fR|\fB\-\-output\-format\fR] [\fB\-S\fR|\fB\-\-stack\-size\fR] [\fB\-j\fR|\fB\-\-output\-json\fR] [\fB\-M\fR|\fB\-\-mtime\fR] [\fB\-A\fR|\fB\-\-atime\fR] [\fB\-y\fR|\fB\-\-ctime\fR] [\fB\-\-files0\-from\fR] [\fB\-m\fR|\fB\-\-filetime\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fIPATH\fR]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Like du but more intuitive
|
Like du but more intuitive
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
@@ -115,6 +115,13 @@ just like \-mtime, but based on file change time
|
|||||||
\fB\-\-files0\-from\fR
|
\fB\-\-files0\-from\fR
|
||||||
run dust on NUL\-terminated file names specified in file; if argument is \-, then read names from standard input
|
run dust on NUL\-terminated file names specified in file; if argument is \-, then read names from standard input
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-m\fR, \fB\-\-filetime\fR
|
||||||
|
Directory \*(Aqsize\*(Aq is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time
|
||||||
|
.br
|
||||||
|
|
||||||
|
.br
|
||||||
|
[\fIpossible values: \fRa, c, m]
|
||||||
|
.TP
|
||||||
\fB\-h\fR, \fB\-\-help\fR
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
Print help
|
Print help
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
+12
@@ -294,4 +294,16 @@ pub fn build_cli() -> Command {
|
|||||||
.num_args(1)
|
.num_args(1)
|
||||||
.help("run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input"),
|
.help("run dust on NUL-terminated file names specified in file; if argument is -, then read names from standard input"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("filetime")
|
||||||
|
.short('m')
|
||||||
|
.long("filetime")
|
||||||
|
.num_args(1)
|
||||||
|
.value_parser([
|
||||||
|
PossibleValue::new("a").alias("accessed"),
|
||||||
|
PossibleValue::new("c").alias("changed"),
|
||||||
|
PossibleValue::new("m").alias("modified"),
|
||||||
|
])
|
||||||
|
.help("Directory 'size' is max filetime of child files instead of disk size. while a/c/m for last accessed/changed/modified time"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-1
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::node::FileTime;
|
||||||
use chrono::{Local, TimeZone};
|
use chrono::{Local, TimeZone};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use config_file::FromConfigFile;
|
use config_file::FromConfigFile;
|
||||||
@@ -84,6 +85,20 @@ impl Config {
|
|||||||
})
|
})
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_filetime(&self, options: &ArgMatches) -> Option<FileTime> {
|
||||||
|
let out_fmt = options.get_one::<String>("filetime");
|
||||||
|
match out_fmt {
|
||||||
|
None => None,
|
||||||
|
Some(x) => match x.as_str() {
|
||||||
|
"m" | "modified" => Some(FileTime::Modified),
|
||||||
|
"a" | "accessed" => Some(FileTime::Accessed),
|
||||||
|
"c" | "changed" => Some(FileTime::Changed),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_skip_total(&self, options: &ArgMatches) -> bool {
|
pub fn get_skip_total(&self, options: &ArgMatches) -> bool {
|
||||||
Some(true) == self.skip_total || options.get_flag("skip_total")
|
Some(true) == self.skip_total || options.get_flag("skip_total")
|
||||||
}
|
}
|
||||||
@@ -159,7 +174,7 @@ impl Config {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_created_time_operator(&self, options: &ArgMatches) -> Option<(Operater, i64)> {
|
pub fn get_changed_time_operator(&self, options: &ArgMatches) -> Option<(Operater, i64)> {
|
||||||
get_filter_time_operator(
|
get_filter_time_operator(
|
||||||
options.get_one::<String>("ctime"),
|
options.get_one::<String>("ctime"),
|
||||||
get_current_date_epoch_seconds(),
|
get_current_date_epoch_seconds(),
|
||||||
@@ -259,6 +274,7 @@ mod tests {
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use super::*;
|
use super::*;
|
||||||
use chrono::{Datelike, Timelike};
|
use chrono::{Datelike, Timelike};
|
||||||
|
use clap::builder::PossibleValue;
|
||||||
use clap::{value_parser, Arg, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgMatches, Command};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -338,4 +354,56 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.get_matches_from(args)
|
.get_matches_from(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_filetime() {
|
||||||
|
// No config and no flag.
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), None);
|
||||||
|
|
||||||
|
// Config is not defined and flag is defined as access time
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust", "--filetime", "a"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), Some(FileTime::Accessed));
|
||||||
|
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust", "--filetime", "accessed"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), Some(FileTime::Accessed));
|
||||||
|
|
||||||
|
// Config is not defined and flag is defined as modified time
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust", "--filetime", "m"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), Some(FileTime::Modified));
|
||||||
|
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust", "--filetime", "modified"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), Some(FileTime::Modified));
|
||||||
|
|
||||||
|
// Config is not defined and flag is defined as changed time
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust", "--filetime", "c"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), Some(FileTime::Changed));
|
||||||
|
|
||||||
|
let c = Config::default();
|
||||||
|
let args = get_filetime_args(vec!["dust", "--filetime", "changed"]);
|
||||||
|
assert_eq!(c.get_filetime(&args), Some(FileTime::Changed));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_filetime_args(args: Vec<&str>) -> ArgMatches {
|
||||||
|
Command::new("Dust")
|
||||||
|
.arg(
|
||||||
|
Arg::new("filetime")
|
||||||
|
.short('m')
|
||||||
|
.long("filetime")
|
||||||
|
.num_args(1)
|
||||||
|
.value_parser([
|
||||||
|
PossibleValue::new("a").alias("accessed"),
|
||||||
|
PossibleValue::new("c").alias("changed"),
|
||||||
|
PossibleValue::new("m").alias("modified"),
|
||||||
|
])
|
||||||
|
.help("Directory 'size' is max filetime of child files instead of disk size. while a/c/m for accessed/changed/modified time"),
|
||||||
|
)
|
||||||
|
.get_matches_from(args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-13
@@ -21,6 +21,7 @@ use std::collections::HashSet;
|
|||||||
use crate::node::build_node;
|
use crate::node::build_node;
|
||||||
use std::fs::DirEntry;
|
use std::fs::DirEntry;
|
||||||
|
|
||||||
|
use crate::node::FileTime;
|
||||||
use crate::platform::get_metadata;
|
use crate::platform::get_metadata;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -40,6 +41,7 @@ pub struct WalkData<'a> {
|
|||||||
pub filter_changed_time: Option<(Operater, i64)>,
|
pub filter_changed_time: Option<(Operater, i64)>,
|
||||||
pub use_apparent_size: bool,
|
pub use_apparent_size: bool,
|
||||||
pub by_filecount: bool,
|
pub by_filecount: bool,
|
||||||
|
pub by_filetime: &'a Option<FileTime>,
|
||||||
pub ignore_hidden: bool,
|
pub ignore_hidden: bool,
|
||||||
pub follow_links: bool,
|
pub follow_links: bool,
|
||||||
pub progress_data: Arc<PAtomicInfo>,
|
pub progress_data: Arc<PAtomicInfo>,
|
||||||
@@ -57,19 +59,15 @@ pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: &WalkData) -> Vec<Node> {
|
|||||||
|
|
||||||
prog_data.state.store(Operation::PREPARING, ORDERING);
|
prog_data.state.store(Operation::PREPARING, ORDERING);
|
||||||
|
|
||||||
clean_inodes(node, &mut inodes, walk_data.use_apparent_size)
|
clean_inodes(node, &mut inodes, walk_data)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
top_level_nodes
|
top_level_nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove files which have the same inode, we don't want to double count them.
|
// Remove files which have the same inode, we don't want to double count them.
|
||||||
fn clean_inodes(
|
fn clean_inodes(x: Node, inodes: &mut HashSet<(u64, u64)>, walk_data: &WalkData) -> Option<Node> {
|
||||||
x: Node,
|
if !walk_data.use_apparent_size {
|
||||||
inodes: &mut HashSet<(u64, u64)>,
|
|
||||||
use_apparent_size: bool,
|
|
||||||
) -> Option<Node> {
|
|
||||||
if !use_apparent_size {
|
|
||||||
if let Some(id) = x.inode_device {
|
if let Some(id) = x.inode_device {
|
||||||
if !inodes.insert(id) {
|
if !inodes.insert(id) {
|
||||||
return None;
|
return None;
|
||||||
@@ -82,12 +80,25 @@ fn clean_inodes(
|
|||||||
tmp.sort_by(sort_by_inode);
|
tmp.sort_by(sort_by_inode);
|
||||||
let new_children: Vec<_> = tmp
|
let new_children: Vec<_> = tmp
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|c| clean_inodes(c, inodes, use_apparent_size))
|
.filter_map(|c| clean_inodes(c, inodes, walk_data))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let actual_size = if walk_data.by_filetime.is_some() {
|
||||||
|
// If by_filetime is Some, directory 'size' is the maximum filetime among child files instead of disk size
|
||||||
|
new_children
|
||||||
|
.iter()
|
||||||
|
.map(|c| c.size)
|
||||||
|
.chain(std::iter::once(x.size))
|
||||||
|
.max()
|
||||||
|
.unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
// If by_filetime is None, directory 'size' is the sum of disk sizes or file counts of child files
|
||||||
|
x.size + new_children.iter().map(|c| c.size).sum::<u64>()
|
||||||
|
};
|
||||||
|
|
||||||
Some(Node {
|
Some(Node {
|
||||||
name: x.name,
|
name: x.name,
|
||||||
size: x.size + new_children.iter().map(|c| c.size).sum::<u64>(),
|
size: actual_size,
|
||||||
children: new_children,
|
children: new_children,
|
||||||
inode_device: x.inode_device,
|
inode_device: x.inode_device,
|
||||||
depth: x.depth,
|
depth: x.depth,
|
||||||
@@ -280,17 +291,43 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn create_walker<'a>(use_apparent_size: bool) -> WalkData<'a> {
|
||||||
|
use crate::PIndicator;
|
||||||
|
let indicator = PIndicator::build_me();
|
||||||
|
WalkData {
|
||||||
|
ignore_directories: HashSet::new(),
|
||||||
|
filter_regex: &[],
|
||||||
|
invert_filter_regex: &[],
|
||||||
|
allowed_filesystems: HashSet::new(),
|
||||||
|
filter_modified_time: Some((Operater::GreaterThan, 0)),
|
||||||
|
filter_accessed_time: Some((Operater::GreaterThan, 0)),
|
||||||
|
filter_changed_time: Some((Operater::GreaterThan, 0)),
|
||||||
|
use_apparent_size,
|
||||||
|
by_filecount: false,
|
||||||
|
by_filetime: &None,
|
||||||
|
ignore_hidden: false,
|
||||||
|
follow_links: false,
|
||||||
|
progress_data: indicator.data.clone(),
|
||||||
|
errors: Arc::new(Mutex::new(RuntimeErrors::default())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(clippy::redundant_clone)]
|
#[allow(clippy::redundant_clone)]
|
||||||
fn test_should_ignore_file() {
|
fn test_should_ignore_file() {
|
||||||
let mut inodes = HashSet::new();
|
let mut inodes = HashSet::new();
|
||||||
let n = create_node();
|
let n = create_node();
|
||||||
|
let walkdata = create_walker(false);
|
||||||
|
|
||||||
// First time we insert the node
|
// First time we insert the node
|
||||||
assert_eq!(clean_inodes(n.clone(), &mut inodes, false), Some(n.clone()));
|
assert_eq!(
|
||||||
|
clean_inodes(n.clone(), &mut inodes, &walkdata),
|
||||||
|
Some(n.clone())
|
||||||
|
);
|
||||||
|
|
||||||
// Second time is a duplicate - we ignore it
|
// Second time is a duplicate - we ignore it
|
||||||
assert_eq!(clean_inodes(n.clone(), &mut inodes, false), None);
|
assert_eq!(clean_inodes(n.clone(), &mut inodes, &walkdata), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -298,10 +335,17 @@ mod tests {
|
|||||||
fn test_should_not_ignore_files_if_using_apparent_size() {
|
fn test_should_not_ignore_files_if_using_apparent_size() {
|
||||||
let mut inodes = HashSet::new();
|
let mut inodes = HashSet::new();
|
||||||
let n = create_node();
|
let n = create_node();
|
||||||
|
let walkdata = create_walker(true);
|
||||||
|
|
||||||
// If using apparent size we include Nodes, even if duplicate inodes
|
// If using apparent size we include Nodes, even if duplicate inodes
|
||||||
assert_eq!(clean_inodes(n.clone(), &mut inodes, true), Some(n.clone()));
|
assert_eq!(
|
||||||
assert_eq!(clean_inodes(n.clone(), &mut inodes, true), Some(n.clone()));
|
clean_inodes(n.clone(), &mut inodes, &walkdata),
|
||||||
|
Some(n.clone())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
clean_inodes(n.clone(), &mut inodes, &walkdata),
|
||||||
|
Some(n.clone())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::display_node::DisplayNode;
|
use crate::display_node::DisplayNode;
|
||||||
|
use crate::node::FileTime;
|
||||||
|
|
||||||
use ansi_term::Colour::Red;
|
use ansi_term::Colour::Red;
|
||||||
use lscolors::{LsColors, Style};
|
use lscolors::{LsColors, Style};
|
||||||
@@ -7,6 +8,7 @@ use unicode_width::UnicodeWidthStr;
|
|||||||
|
|
||||||
use stfu8::encode_u8;
|
use stfu8::encode_u8;
|
||||||
|
|
||||||
|
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@@ -16,12 +18,14 @@ use thousands::Separable;
|
|||||||
|
|
||||||
pub static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];
|
pub static UNITS: [char; 4] = ['T', 'G', 'M', 'K'];
|
||||||
static BLOCKS: [char; 5] = ['█', '▓', '▒', '░', ' '];
|
static BLOCKS: [char; 5] = ['█', '▓', '▒', '░', ' '];
|
||||||
|
const FILETIME_SHOW_LENGTH: usize = 19;
|
||||||
|
|
||||||
pub struct InitialDisplayData {
|
pub struct InitialDisplayData {
|
||||||
pub short_paths: bool,
|
pub short_paths: bool,
|
||||||
pub is_reversed: bool,
|
pub is_reversed: bool,
|
||||||
pub colors_on: bool,
|
pub colors_on: bool,
|
||||||
pub by_filecount: bool,
|
pub by_filecount: bool,
|
||||||
|
pub by_filetime: Option<FileTime>,
|
||||||
pub is_screen_reader: bool,
|
pub is_screen_reader: bool,
|
||||||
pub output_format: String,
|
pub output_format: String,
|
||||||
pub bars_on_right: bool,
|
pub bars_on_right: bool,
|
||||||
@@ -141,6 +145,8 @@ pub fn draw_it(
|
|||||||
let num_chars_needed_on_left_most = if idd.by_filecount {
|
let num_chars_needed_on_left_most = if idd.by_filecount {
|
||||||
let max_size = biggest.size;
|
let max_size = biggest.size;
|
||||||
max_size.separate_with_commas().chars().count()
|
max_size.separate_with_commas().chars().count()
|
||||||
|
} else if idd.by_filetime.is_some() {
|
||||||
|
FILETIME_SHOW_LENGTH
|
||||||
} else {
|
} else {
|
||||||
find_biggest_size_str(root_node, &idd.output_format)
|
find_biggest_size_str(root_node, &idd.output_format)
|
||||||
};
|
};
|
||||||
@@ -342,6 +348,8 @@ pub fn format_string(
|
|||||||
if display_data.initial.is_screen_reader {
|
if display_data.initial.is_screen_reader {
|
||||||
// if screen_reader then bars is 'depth'
|
// if screen_reader then bars is 'depth'
|
||||||
format!("{pretty_name} {bars} {pretty_size}{percent}")
|
format!("{pretty_name} {bars} {pretty_size}{percent}")
|
||||||
|
} else if display_data.initial.by_filetime.is_some() {
|
||||||
|
format!("{pretty_size} {indent}{pretty_name}")
|
||||||
} else {
|
} else {
|
||||||
format!("{pretty_size} {indent} {pretty_name}{percent}")
|
format!("{pretty_size} {indent} {pretty_name}{percent}")
|
||||||
}
|
}
|
||||||
@@ -376,6 +384,8 @@ fn get_name_percent(
|
|||||||
fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayData) -> String {
|
fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayData) -> String {
|
||||||
let output = if display_data.initial.by_filecount {
|
let output = if display_data.initial.by_filecount {
|
||||||
node.size.separate_with_commas()
|
node.size.separate_with_commas()
|
||||||
|
} else if display_data.initial.by_filetime.is_some() {
|
||||||
|
get_pretty_file_modified_time(node.size as i64)
|
||||||
} else {
|
} else {
|
||||||
human_readable_number(node.size, &display_data.initial.output_format)
|
human_readable_number(node.size, &display_data.initial.output_format)
|
||||||
};
|
};
|
||||||
@@ -389,6 +399,14 @@ fn get_pretty_size(node: &DisplayNode, is_biggest: bool, display_data: &DisplayD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_pretty_file_modified_time(timestamp: i64) -> String {
|
||||||
|
let datetime: DateTime<Utc> = Utc.timestamp_opt(timestamp, 0).unwrap();
|
||||||
|
|
||||||
|
let local_datetime = datetime.with_timezone(&Local);
|
||||||
|
|
||||||
|
local_datetime.format("%Y-%m-%dT%H:%M:%S").to_string()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_pretty_name(
|
fn get_pretty_name(
|
||||||
node: &DisplayNode,
|
node: &DisplayNode,
|
||||||
name_and_padding: String,
|
name_and_padding: String,
|
||||||
@@ -469,6 +487,7 @@ mod tests {
|
|||||||
is_reversed: false,
|
is_reversed: false,
|
||||||
colors_on: false,
|
colors_on: false,
|
||||||
by_filecount: false,
|
by_filecount: false,
|
||||||
|
by_filetime: None,
|
||||||
is_screen_reader: false,
|
is_screen_reader: false,
|
||||||
output_format: "".into(),
|
output_format: "".into(),
|
||||||
bars_on_right: false,
|
bars_on_right: false,
|
||||||
@@ -625,4 +644,37 @@ mod tests {
|
|||||||
let bar = dd.generate_bar(&n, 5);
|
let bar = dd.generate_bar(&n, 5);
|
||||||
assert_eq!(bar, "████▓▓▓▓▓▓▓▓▓");
|
assert_eq!(bar, "████▓▓▓▓▓▓▓▓▓");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_pretty_file_modified_time() {
|
||||||
|
// Create a timestamp for 2023-07-12 00:00:00 in local time
|
||||||
|
let local_dt = Local.with_ymd_and_hms(2023, 7, 12, 0, 0, 0).unwrap();
|
||||||
|
let timestamp = local_dt.timestamp();
|
||||||
|
|
||||||
|
// Format expected output
|
||||||
|
let expected_output = local_dt.format("%Y-%m-%dT%H:%M:%S").to_string();
|
||||||
|
|
||||||
|
assert_eq!(get_pretty_file_modified_time(timestamp), expected_output);
|
||||||
|
|
||||||
|
// Test another timestamp
|
||||||
|
let local_dt = Local.with_ymd_and_hms(2020, 1, 1, 12, 0, 0).unwrap();
|
||||||
|
let timestamp = local_dt.timestamp();
|
||||||
|
let expected_output = local_dt.format("%Y-%m-%dT%H:%M:%S").to_string();
|
||||||
|
|
||||||
|
assert_eq!(get_pretty_file_modified_time(timestamp), expected_output);
|
||||||
|
|
||||||
|
// Test timestamp for epoch start (1970-01-01T00:00:00)
|
||||||
|
let local_dt = Local.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap();
|
||||||
|
let timestamp = local_dt.timestamp();
|
||||||
|
let expected_output = local_dt.format("%Y-%m-%dT%H:%M:%S").to_string();
|
||||||
|
|
||||||
|
assert_eq!(get_pretty_file_modified_time(timestamp), expected_output);
|
||||||
|
|
||||||
|
// Test a future timestamp
|
||||||
|
let local_dt = Local.with_ymd_and_hms(2030, 12, 25, 6, 30, 0).unwrap();
|
||||||
|
let timestamp = local_dt.timestamp();
|
||||||
|
let expected_output = local_dt.format("%Y-%m-%dT%H:%M:%S").to_string();
|
||||||
|
|
||||||
|
assert_eq!(get_pretty_file_modified_time(timestamp), expected_output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-2
@@ -1,4 +1,5 @@
|
|||||||
use crate::display_node::DisplayNode;
|
use crate::display_node::DisplayNode;
|
||||||
|
use crate::node::FileTime;
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -14,7 +15,11 @@ pub struct AggregateData {
|
|||||||
pub using_a_filter: bool,
|
pub using_a_filter: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_biggest(top_level_nodes: Vec<Node>, display_data: AggregateData) -> Option<DisplayNode> {
|
pub fn get_biggest(
|
||||||
|
top_level_nodes: Vec<Node>,
|
||||||
|
display_data: AggregateData,
|
||||||
|
by_filetime: &Option<FileTime>,
|
||||||
|
) -> Option<DisplayNode> {
|
||||||
if top_level_nodes.is_empty() {
|
if top_level_nodes.is_empty() {
|
||||||
// perhaps change this, bring back Error object?
|
// perhaps change this, bring back Error object?
|
||||||
return None;
|
return None;
|
||||||
@@ -24,7 +29,15 @@ pub fn get_biggest(top_level_nodes: Vec<Node>, display_data: AggregateData) -> O
|
|||||||
let root;
|
let root;
|
||||||
|
|
||||||
if number_top_level_nodes > 1 {
|
if number_top_level_nodes > 1 {
|
||||||
let size = top_level_nodes.iter().map(|node| node.size).sum();
|
let size = if by_filetime.is_some() {
|
||||||
|
top_level_nodes
|
||||||
|
.iter()
|
||||||
|
.map(|node| node.size)
|
||||||
|
.max()
|
||||||
|
.unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
top_level_nodes.iter().map(|node| node.size).sum()
|
||||||
|
};
|
||||||
root = Node {
|
root = Node {
|
||||||
name: PathBuf::from("(total)"),
|
name: PathBuf::from("(total)"),
|
||||||
size,
|
size,
|
||||||
|
|||||||
+19
-3
@@ -1,4 +1,5 @@
|
|||||||
use crate::display_node::DisplayNode;
|
use crate::display_node::DisplayNode;
|
||||||
|
use crate::node::FileTime;
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
@@ -10,7 +11,11 @@ struct ExtensionNode<'a> {
|
|||||||
extension: Option<&'a OsStr>,
|
extension: Option<&'a OsStr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_file_types(top_level_nodes: &[Node], n: usize) -> Option<DisplayNode> {
|
pub fn get_all_file_types(
|
||||||
|
top_level_nodes: &[Node],
|
||||||
|
n: usize,
|
||||||
|
by_filetime: &Option<FileTime>,
|
||||||
|
) -> Option<DisplayNode> {
|
||||||
let ext_nodes = {
|
let ext_nodes = {
|
||||||
let mut extension_cumulative_sizes = HashMap::new();
|
let mut extension_cumulative_sizes = HashMap::new();
|
||||||
build_by_all_file_types(top_level_nodes, &mut extension_cumulative_sizes);
|
build_by_all_file_types(top_level_nodes, &mut extension_cumulative_sizes);
|
||||||
@@ -44,16 +49,27 @@ pub fn get_all_file_types(top_level_nodes: &[Node], n: usize) -> Option<DisplayN
|
|||||||
|
|
||||||
// ...then, aggregate the remaining nodes (if any) into a single "(others)" node
|
// ...then, aggregate the remaining nodes (if any) into a single "(others)" node
|
||||||
if ext_nodes_iter.len() > 0 {
|
if ext_nodes_iter.len() > 0 {
|
||||||
|
let actual_size = if by_filetime.is_some() {
|
||||||
|
ext_nodes_iter.map(|node| node.size).max().unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
ext_nodes_iter.map(|node| node.size).sum()
|
||||||
|
};
|
||||||
displayed.push(DisplayNode {
|
displayed.push(DisplayNode {
|
||||||
name: PathBuf::from("(others)"),
|
name: PathBuf::from("(others)"),
|
||||||
size: ext_nodes_iter.map(|node| node.size).sum(),
|
size: actual_size,
|
||||||
children: vec![],
|
children: vec![],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let actual_size: u64 = if by_filetime.is_some() {
|
||||||
|
displayed.iter().map(|node| node.size).max().unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
displayed.iter().map(|node| node.size).sum()
|
||||||
|
};
|
||||||
|
|
||||||
let result = DisplayNode {
|
let result = DisplayNode {
|
||||||
name: PathBuf::from("(total)"),
|
name: PathBuf::from("(total)"),
|
||||||
size: displayed.iter().map(|node| node.size).sum(),
|
size: actual_size,
|
||||||
children: displayed,
|
children: displayed,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -224,6 +224,7 @@ fn main() {
|
|||||||
.collect::<Vec<Regex>>();
|
.collect::<Vec<Regex>>();
|
||||||
|
|
||||||
let by_filecount = options.get_flag("by_filecount");
|
let by_filecount = options.get_flag("by_filecount");
|
||||||
|
let by_filetime = config.get_filetime(&options);
|
||||||
let limit_filesystem = options.get_flag("limit_filesystem");
|
let limit_filesystem = options.get_flag("limit_filesystem");
|
||||||
let follow_links = options.get_flag("dereference_links");
|
let follow_links = options.get_flag("dereference_links");
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ fn main() {
|
|||||||
|
|
||||||
let filter_modified_time = config.get_modified_time_operator(&options);
|
let filter_modified_time = config.get_modified_time_operator(&options);
|
||||||
let filter_accessed_time = config.get_accessed_time_operator(&options);
|
let filter_accessed_time = config.get_accessed_time_operator(&options);
|
||||||
let filter_changed_time = config.get_created_time_operator(&options);
|
let filter_changed_time = config.get_changed_time_operator(&options);
|
||||||
|
|
||||||
let walk_data = WalkData {
|
let walk_data = WalkData {
|
||||||
ignore_directories: ignored_full_path,
|
ignore_directories: ignored_full_path,
|
||||||
@@ -260,6 +261,7 @@ fn main() {
|
|||||||
filter_changed_time,
|
filter_changed_time,
|
||||||
use_apparent_size: config.get_apparent_size(&options),
|
use_apparent_size: config.get_apparent_size(&options),
|
||||||
by_filecount,
|
by_filecount,
|
||||||
|
by_filetime: &by_filetime,
|
||||||
ignore_hidden,
|
ignore_hidden,
|
||||||
follow_links,
|
follow_links,
|
||||||
progress_data: indicator.data.clone(),
|
progress_data: indicator.data.clone(),
|
||||||
@@ -272,7 +274,7 @@ fn main() {
|
|||||||
let top_level_nodes = walk_it(simplified_dirs, &walk_data);
|
let top_level_nodes = walk_it(simplified_dirs, &walk_data);
|
||||||
|
|
||||||
let tree = match summarize_file_types {
|
let tree = match 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, &by_filetime),
|
||||||
false => {
|
false => {
|
||||||
let agg_data = AggregateData {
|
let agg_data = AggregateData {
|
||||||
min_size: config.get_min_size(&options),
|
min_size: config.get_min_size(&options),
|
||||||
@@ -282,7 +284,7 @@ fn main() {
|
|||||||
depth,
|
depth,
|
||||||
using_a_filter: !filter_regexs.is_empty() || !invert_filter_regexs.is_empty(),
|
using_a_filter: !filter_regexs.is_empty() || !invert_filter_regexs.is_empty(),
|
||||||
};
|
};
|
||||||
get_biggest(top_level_nodes, agg_data)
|
get_biggest(top_level_nodes, agg_data, &by_filetime)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -334,6 +336,7 @@ fn main() {
|
|||||||
is_reversed: !config.get_reverse(&options),
|
is_reversed: !config.get_reverse(&options),
|
||||||
colors_on: is_colors,
|
colors_on: is_colors,
|
||||||
by_filecount,
|
by_filecount,
|
||||||
|
by_filetime,
|
||||||
is_screen_reader: config.get_screen_reader(&options),
|
is_screen_reader: config.get_screen_reader(&options),
|
||||||
output_format,
|
output_format,
|
||||||
bars_on_right: config.get_bars_on_right(&options),
|
bars_on_right: config.get_bars_on_right(&options),
|
||||||
|
|||||||
+15
@@ -16,6 +16,13 @@ pub struct Node {
|
|||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum FileTime {
|
||||||
|
Modified,
|
||||||
|
Accessed,
|
||||||
|
Changed,
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn build_node(
|
pub fn build_node(
|
||||||
dir: PathBuf,
|
dir: PathBuf,
|
||||||
@@ -27,6 +34,7 @@ pub fn build_node(
|
|||||||
) -> Option<Node> {
|
) -> Option<Node> {
|
||||||
let use_apparent_size = walk_data.use_apparent_size;
|
let use_apparent_size = walk_data.use_apparent_size;
|
||||||
let by_filecount = walk_data.by_filecount;
|
let by_filecount = walk_data.by_filecount;
|
||||||
|
let by_filetime = &walk_data.by_filetime;
|
||||||
|
|
||||||
get_metadata(
|
get_metadata(
|
||||||
&dir,
|
&dir,
|
||||||
@@ -51,6 +59,13 @@ pub fn build_node(
|
|||||||
0
|
0
|
||||||
} else if by_filecount {
|
} else if by_filecount {
|
||||||
1
|
1
|
||||||
|
} else if by_filetime.is_some() {
|
||||||
|
match by_filetime {
|
||||||
|
Some(FileTime::Modified) => data.2 .0.unsigned_abs(),
|
||||||
|
Some(FileTime::Accessed) => data.2 .1.unsigned_abs(),
|
||||||
|
Some(FileTime::Changed) => data.2 .2.unsigned_abs(),
|
||||||
|
None => unreachable!(),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
data.0
|
data.0
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user