diff options
author | Piotr Wach <pwach@bloomberg.net> | 2024-01-10 22:30:20 +0000 |
---|---|---|
committer | Piotr Wach <pwach@bloomberg.net> | 2024-01-14 15:01:10 +0000 |
commit | 226cbb8b2d6388ddd7a7e48fdac1a4db2ee75474 (patch) | |
tree | 1522244207da554e65d209e7f1c203fd13f6912f /src | |
parent | 30d8dd5fb54ef6db8b4444524407f15db25d7b02 (diff) |
Traverse children vs parent & fix parent node size after refresh
Diffstat (limited to 'src')
-rw-r--r-- | src/aggregate.rs | 2 | ||||
-rw-r--r-- | src/common.rs | 3 | ||||
-rw-r--r-- | src/interactive/app/eventloop.rs | 41 | ||||
-rw-r--r-- | src/interactive/app/handlers.rs | 2 | ||||
-rw-r--r-- | src/interactive/app/terminal.rs | 2 | ||||
-rw-r--r-- | src/interactive/app/tree_view.rs | 5 | ||||
-rw-r--r-- | src/traverse.rs | 32 |
7 files changed, 55 insertions, 32 deletions
diff --git a/src/aggregate.rs b/src/aggregate.rs index ec4d5ae..356a1a9 100644 --- a/src/aggregate.rs +++ b/src/aggregate.rs @@ -41,7 +41,7 @@ pub fn aggregate( continue; } }; - for entry in walk_options.iter_from_path(path.as_ref(), device_id) { + for entry in walk_options.iter_from_path(path.as_ref(), device_id, false) { stats.entries_traversed += 1; progress.throttled(|| { if let Some(err) = err.as_mut() { diff --git a/src/common.rs b/src/common.rs index 254fbbf..8bd0451 100644 --- a/src/common.rs +++ b/src/common.rs @@ -176,11 +176,12 @@ pub struct WalkOptions { type WalkDir = jwalk::WalkDirGeneric<((), Option<Result<std::fs::Metadata, jwalk::Error>>)>; impl WalkOptions { - pub fn iter_from_path(&self, root: &Path, root_device_id: u64) -> WalkDir { + pub fn iter_from_path(&self, root: &Path, root_device_id: u64, skip_root: bool) -> WalkDir { let ignore_dirs = self.ignore_dirs.clone(); let cwd = std::env::current_dir().unwrap_or_else(|_| root.to_owned()); WalkDir::new(root) .follow_links(false) + .min_depth(if skip_root { 1 } else { 0 }) .sort(match self.sorting { TraversalSorting::None => false, TraversalSorting::AlphabeticalByFileName => true, diff --git a/src/interactive/app/eventloop.rs b/src/interactive/app/eventloop.rs index b370f78..5ce8cd6 100644 --- a/src/interactive/app/eventloop.rs +++ b/src/interactive/app/eventloop.rs @@ -66,7 +66,7 @@ impl AppState { pub fn traverse(&mut self, traversal: &Traversal, input: Vec<PathBuf>) -> Result<()> { let background_traversal = - BackgroundTraversal::start(traversal.root_index, &self.walk_options, input)?; + BackgroundTraversal::start(traversal.root_index, &self.walk_options, input, false)?; self.navigation_mut().view_root = traversal.root_index; self.active_traversal = Some(background_traversal); Ok(()) @@ -125,7 +125,7 @@ impl AppState { crossbeam::select! { recv(events) -> event => { let Ok(event) = event else { - return Ok(Some(WalkResult { num_errors: 0 })); + return Ok(Some(WalkResult { num_errors: traversal.io_errors })); }; let res = self.process_terminal_event( window, @@ -153,7 +153,7 @@ impl AppState { } } else { let Ok(event) = events.recv() else { - return Ok(Some(WalkResult { num_errors: 0 })); + return Ok(Some(WalkResult { num_errors: traversal.io_errors })); }; let result = self.process_terminal_event(window, traversal, display, terminal, event)?; @@ -309,23 +309,30 @@ impl AppState { } fn refresh(&mut self, tree: &mut TreeView<'_>, what: Refresh) -> anyhow::Result<()> { + // TODO: we should refresh parent_idx not selected index match what { Refresh::Selected => { - if let Some(selected) = self.navigation().selected { - let parent_idx = tree - .fs_parent_of(selected) - .expect("there is always a parent to a selection"); - let path = tree.path_of(selected); - tree.remove_entries(selected); - tree.recompute_sizes_recursively(parent_idx); - self.entries = tree.sorted_entries(parent_idx, self.sorting); - self.navigation_mut().selected = self.entries.first().map(|e| e.index); - self.active_traversal = Some(BackgroundTraversal::start( - parent_idx, - &self.walk_options, - vec![path], - )?); + let mut path = tree.path_of(self.navigation().view_root); + if path.to_str().unwrap() == "" { + path = PathBuf::from("."); } + log::info!("Refreshing {:?}", path); + + let entries_deleted = tree.remove_entries(self.navigation().view_root, false); + log::info!("Deleted {entries_deleted} entries"); + + tree.recompute_sizes_recursively(self.navigation().view_root); + self.entries = tree.sorted_entries(self.navigation().view_root, self.sorting); + self.navigation_mut().selected = self.entries.first().map(|e| e.index); + + self.active_traversal = Some(BackgroundTraversal::start( + self.navigation().view_root, + &self.walk_options, + vec![path], + true, + )?); + + self.received_events = false; } Refresh::AllInView => { log::info!("Not implemented") diff --git a/src/interactive/app/handlers.rs b/src/interactive/app/handlers.rs index 754fa51..32a63ab 100644 --- a/src/interactive/app/handlers.rs +++ b/src/interactive/app/handlers.rs @@ -312,7 +312,7 @@ impl AppState { let parent_idx = tree_view .fs_parent_of(index) .expect("us being unable to delete the root index"); - let entries_deleted = tree_view.remove_entries(index); + let entries_deleted = tree_view.remove_entries(index, true); if !tree_view.exists(self.navigation().view_root) { self.go_to_root(tree_view); diff --git a/src/interactive/app/terminal.rs b/src/interactive/app/terminal.rs index 64c68af..6672188 100644 --- a/src/interactive/app/terminal.rs +++ b/src/interactive/app/terminal.rs @@ -120,7 +120,7 @@ mod tests { return Ok(res); } } - Ok(WalkResult { num_errors: 0 }) + Ok(WalkResult { num_errors: self.traversal.io_errors }) } } } diff --git a/src/interactive/app/tree_view.rs b/src/interactive/app/tree_view.rs index 74ec4fa..2126206 100644 --- a/src/interactive/app/tree_view.rs +++ b/src/interactive/app/tree_view.rs @@ -59,11 +59,14 @@ impl TreeView<'_> { current_path(&self.traversal.tree, view_root, self.glob_tree_root) } - pub fn remove_entries(&mut self, index: TreeIndex) -> usize { + pub fn remove_entries(&mut self, index: TreeIndex, remove_index: bool) -> usize { let mut entries_deleted = 0; let mut bfs = Bfs::new(self.tree(), index); while let Some(nx) = bfs.next(&self.tree()) { + if nx == index && !remove_index { + continue; + } self.tree_mut().remove_node(nx); self.traversal.entries_traversed -= 1; entries_deleted += 1; diff --git a/src/traverse.rs b/src/traverse.rs index 6c24788..b879698 100644 --- a/src/traverse.rs +++ b/src/traverse.rs @@ -72,9 +72,9 @@ pub struct Traversal { } impl Traversal { - pub fn recompute_root_size(&self) -> u128 { + pub fn recompute_node_size(&self, node_index: TreeIndex) -> u128 { self.tree - .neighbors_directed(self.root_index, Direction::Outgoing) + .neighbors_directed(node_index, Direction::Outgoing) .map(|idx| get_size_or_panic(&self.tree, idx)) .sum() } @@ -134,6 +134,7 @@ pub enum TraversalEvent { /// An in-progress traversal which exposes newly obtained entries pub struct BackgroundTraversal { walk_options: WalkOptions, + root_idx: TreeIndex, previous_node_idx: TreeIndex, parent_node_idx: TreeIndex, directory_info_per_depth_level: Vec<EntryInfo>, @@ -141,6 +142,7 @@ pub struct BackgroundTraversal { previous_depth: usize, inodes: InodeFilter, throttle: Option<Throttle>, + skip_root: bool, pub event_rx: Receiver<TraversalEvent>, } @@ -151,6 +153,7 @@ impl BackgroundTraversal { root_idx: TreeIndex, walk_options: &WalkOptions, input: Vec<PathBuf>, + skip_root: bool, ) -> anyhow::Result<BackgroundTraversal> { let (entry_tx, entry_rx) = crossbeam::channel::bounded(100); std::thread::Builder::new() @@ -160,6 +163,7 @@ impl BackgroundTraversal { let mut io_errors: u64 = 0; move || { for root_path in input.into_iter() { + log::info!("Walking {root_path:?}"); let device_id = match crossdev::init(root_path.as_ref()) { Ok(id) => id, Err(_) => { @@ -170,9 +174,10 @@ impl BackgroundTraversal { let root_path = Arc::new(root_path); for entry in walk_options - .iter_from_path(root_path.as_ref(), device_id) + .iter_from_path(root_path.as_ref(), device_id, skip_root) .into_iter() { + log::info!("{:?}", entry); if entry_tx .send(TraversalEvent::Entry( entry, @@ -195,6 +200,7 @@ impl BackgroundTraversal { Ok(Self { walk_options: walk_options.clone(), + root_idx, previous_node_idx: root_idx, parent_node_idx: root_idx, directory_info_per_depth_level: Vec::new(), @@ -202,6 +208,7 @@ impl BackgroundTraversal { previous_depth: 0, inodes: InodeFilter::default(), throttle: Some(Throttle::new(Duration::from_millis(250), None)), + skip_root, event_rx: entry_rx, }) } @@ -223,12 +230,17 @@ impl BackgroundTraversal { t.entries_traversed += 1; let mut data = EntryData::default(); match entry { - Ok(entry) => { - data.name = if entry.depth < 1 { - (*root_path).clone() + Ok(mut entry) => { + if self.skip_root { + entry.depth = entry.depth - 1; + data.name = entry.file_name.into() } else { - entry.file_name.into() - }; + data.name = if entry.depth < 1 { + (*root_path).clone() + } else { + entry.file_name.into() + } + } let mut file_size = 0u128; let mut mtime: SystemTime = UNIX_EPOCH; @@ -360,10 +372,10 @@ impl BackgroundTraversal { ); self.parent_node_idx = parent_or_panic(&mut t.tree, self.parent_node_idx); } - let root_size = t.recompute_root_size(); + let root_size = t.recompute_node_size(self.root_idx); set_entry_info_or_panic( &mut t.tree, - t.root_index, + self.root_idx, EntryInfo { size: root_size, entries_count: (t.entries_traversed > 0).then_some(t.entries_traversed), |