Skip to content

Commit

Permalink
Traverse children vs parent & fix parent node size after refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrwach committed Jan 14, 2024
1 parent 30d8dd5 commit 226cbb8
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
3 changes: 2 additions & 1 deletion src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
41 changes: 24 additions & 17 deletions src/interactive/app/eventloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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")
Expand Down
2 changes: 1 addition & 1 deletion src/interactive/app/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/interactive/app/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ mod tests {
return Ok(res);
}
}
Ok(WalkResult { num_errors: 0 })
Ok(WalkResult { num_errors: self.traversal.io_errors })
}
}
}
5 changes: 4 additions & 1 deletion src/interactive/app/tree_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
32 changes: 22 additions & 10 deletions src/traverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down Expand Up @@ -134,13 +134,15 @@ 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>,
current_directory_at_depth: EntryInfo,
previous_depth: usize,
inodes: InodeFilter,
throttle: Option<Throttle>,
skip_root: bool,
pub event_rx: Receiver<TraversalEvent>,
}

Expand All @@ -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()
Expand All @@ -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(_) => {
Expand All @@ -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,
Expand All @@ -195,13 +200,15 @@ 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(),
current_directory_at_depth: EntryInfo::default(),
previous_depth: 0,
inodes: InodeFilter::default(),
throttle: Some(Throttle::new(Duration::from_millis(250), None)),
skip_root,
event_rx: entry_rx,
})
}
Expand All @@ -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;
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit 226cbb8

Please sign in to comment.