|
1 | 1 | use crate::interactive::path_of; |
2 | | -use dua::traverse::{EntryData, Tree, TreeIndex}; |
| 2 | +use dua::traverse::{Tree, TreeIndex}; |
3 | 3 | use itertools::Itertools; |
4 | 4 | use petgraph::Direction; |
5 | | -use std::cmp::Ordering; |
| 5 | +use std::time::SystemTime; |
| 6 | +use std::{cmp::Ordering, path::PathBuf}; |
6 | 7 | use unicode_segmentation::UnicodeSegmentation; |
7 | 8 |
|
8 | 9 | #[derive(Default, Debug, Copy, Clone, PartialOrd, PartialEq, Eq)] |
@@ -47,37 +48,61 @@ impl SortMode { |
47 | 48 |
|
48 | 49 | pub struct EntryDataBundle { |
49 | 50 | pub index: TreeIndex, |
50 | | - pub data: EntryData, |
| 51 | + pub name: PathBuf, |
| 52 | + pub size: u128, |
| 53 | + pub mtime: SystemTime, |
| 54 | + pub entry_count: Option<u64>, |
51 | 55 | pub is_dir: bool, |
52 | 56 | pub exists: bool, |
53 | 57 | } |
54 | 58 |
|
55 | | -pub fn sorted_entries(tree: &Tree, node_idx: TreeIndex, sorting: SortMode) -> Vec<EntryDataBundle> { |
| 59 | +/// Note that with `glob_root` present, we will not obtain metadata anymore as we might be seeing |
| 60 | +/// a lot of entries. That way, displaying 250k entries is no problem. |
| 61 | +pub fn sorted_entries( |
| 62 | + tree: &Tree, |
| 63 | + node_idx: TreeIndex, |
| 64 | + sorting: SortMode, |
| 65 | + glob_root: Option<TreeIndex>, |
| 66 | +) -> Vec<EntryDataBundle> { |
56 | 67 | use SortMode::*; |
57 | 68 | fn cmp_count(l: &EntryDataBundle, r: &EntryDataBundle) -> Ordering { |
58 | | - l.data |
59 | | - .entry_count |
60 | | - .cmp(&r.data.entry_count) |
61 | | - .then_with(|| l.data.name.cmp(&r.data.name)) |
| 69 | + l.entry_count |
| 70 | + .cmp(&r.entry_count) |
| 71 | + .then_with(|| l.name.cmp(&r.name)) |
62 | 72 | } |
63 | 73 | tree.neighbors_directed(node_idx, Direction::Outgoing) |
64 | 74 | .filter_map(|idx| { |
65 | | - tree.node_weight(idx).map(|w| { |
66 | | - let p = path_of(tree, idx); |
67 | | - let pm = p.symlink_metadata(); |
| 75 | + tree.node_weight(idx).map(|entry| { |
| 76 | + let use_glob_path = glob_root.map_or(false, |glob_root| glob_root == node_idx); |
| 77 | + let (path, exists, is_dir) = { |
| 78 | + let path = path_of(tree, idx, glob_root); |
| 79 | + if glob_root.is_some() { |
| 80 | + (path, true, entry.is_dir) |
| 81 | + } else { |
| 82 | + let meta = path.symlink_metadata(); |
| 83 | + (path, meta.is_ok(), meta.ok().map_or(false, |m| m.is_dir())) |
| 84 | + } |
| 85 | + }; |
68 | 86 | EntryDataBundle { |
69 | 87 | index: idx, |
70 | | - data: w.clone(), |
71 | | - exists: pm.is_ok(), |
72 | | - is_dir: pm.ok().map_or(false, |m| m.is_dir()), |
| 88 | + name: if use_glob_path { |
| 89 | + path |
| 90 | + } else { |
| 91 | + entry.name.clone() |
| 92 | + }, |
| 93 | + size: entry.size, |
| 94 | + mtime: entry.mtime, |
| 95 | + entry_count: entry.entry_count, |
| 96 | + exists, |
| 97 | + is_dir, |
73 | 98 | } |
74 | 99 | }) |
75 | 100 | }) |
76 | 101 | .sorted_by(|l, r| match sorting { |
77 | | - SizeDescending => r.data.size.cmp(&l.data.size), |
78 | | - SizeAscending => l.data.size.cmp(&r.data.size), |
79 | | - MTimeAscending => l.data.mtime.cmp(&r.data.mtime), |
80 | | - MTimeDescending => r.data.mtime.cmp(&l.data.mtime), |
| 102 | + SizeDescending => r.size.cmp(&l.size), |
| 103 | + SizeAscending => l.size.cmp(&r.size), |
| 104 | + MTimeAscending => l.mtime.cmp(&r.mtime), |
| 105 | + MTimeDescending => r.mtime.cmp(&l.mtime), |
81 | 106 | CountAscending => cmp_count(l, r), |
82 | 107 | CountDescending => cmp_count(l, r).reverse(), |
83 | 108 | }) |
|
0 commit comments