Skip to content

Commit

Permalink
Merge branch 'no-entry-check'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Jan 23, 2024
2 parents 600bee2 + 78b9a8e commit d837d72
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 21 deletions.
19 changes: 17 additions & 2 deletions src/interactive/app/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,29 @@ pub struct EntryDataBundle {
pub exists: bool,
}

pub enum EntryCheck {
PossiblyCostlyLstat,
Disabled,
}

impl EntryCheck {
pub fn new(is_scanning: bool, allow_entry_check: bool) -> Self {
if allow_entry_check && !is_scanning {
EntryCheck::PossiblyCostlyLstat
} else {
EntryCheck::Disabled
}
}
}

/// Note that with `glob_root` present, we will not obtain metadata anymore as we might be seeing
/// a lot of entries. That way, displaying 250k entries is no problem.
pub fn sorted_entries(
tree: &Tree,
node_idx: TreeIndex,
sorting: SortMode,
glob_root: Option<TreeIndex>,
is_scanning: bool,
check: EntryCheck,
) -> Vec<EntryDataBundle> {
use SortMode::*;
fn cmp_count(l: &EntryDataBundle, r: &EntryDataBundle) -> Ordering {
Expand All @@ -77,7 +92,7 @@ pub fn sorted_entries(
let use_glob_path = glob_root.map_or(false, |glob_root| glob_root == node_idx);
let (path, exists, is_dir) = {
let path = path_of(tree, idx, glob_root);
if is_scanning || glob_root == Some(node_idx) {
if matches!(check, EntryCheck::Disabled) || glob_root == Some(node_idx) {
(path, true, entry.is_dir)
} else {
let meta = path.symlink_metadata();
Expand Down
14 changes: 9 additions & 5 deletions src/interactive/app/eventloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::interactive::{
app::navigation::Navigation,
state::FocussedPane,
widgets::{glob_search, MainWindow, MainWindowProps},
CursorDirection, CursorMode, DisplayOptions, MarkEntryMode,
CursorDirection, CursorMode, DisplayOptions, EntryCheck, MarkEntryMode,
};
use anyhow::Result;
use crossbeam::channel::Receiver;
Expand Down Expand Up @@ -197,7 +197,7 @@ impl AppState {
self.entries = tree_view.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);

if !self.received_events {
Expand All @@ -217,6 +217,10 @@ impl AppState {
self.reset_message(); // force "scanning" to appear
}

pub(crate) fn entry_check(&self) -> EntryCheck {
EntryCheck::new(self.scan.is_some(), self.allow_entry_check)
}

fn process_terminal_event<B>(
&mut self,
window: &mut MainWindow,
Expand Down Expand Up @@ -443,7 +447,7 @@ impl AppState {
self.entries = tree.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);
self.navigation_mut().selected = self.entries.first().map(|e| e.index);

Expand Down Expand Up @@ -498,7 +502,7 @@ impl AppState {
glob_tree_root: Some(tree_root),
};
let new_entries =
glob_tree_view.sorted_entries(tree_root, self.sorting, self.scan.is_some());
glob_tree_view.sorted_entries(tree_root, self.sorting, self.entry_check());

let new_entries = self
.navigation_mut()
Expand Down Expand Up @@ -553,7 +557,7 @@ impl AppState {
self.entries = tree_view.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/interactive/app/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl AppState {
.map(|parent_idx| {
(
parent_idx,
tree_view.sorted_entries(parent_idx, self.sorting, self.scan.is_some()),
tree_view.sorted_entries(parent_idx, self.sorting, self.entry_check()),
)
})
}
Expand All @@ -89,7 +89,7 @@ impl AppState {
self.navigation().selected.map(|previously_selected| {
(
previously_selected,
tree_view.sorted_entries(previously_selected, self.sorting, self.scan.is_some()),
tree_view.sorted_entries(previously_selected, self.sorting, self.entry_check()),
)
})
}
Expand Down Expand Up @@ -125,7 +125,7 @@ impl AppState {
self.entries = tree_view.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);
}

Expand All @@ -134,7 +134,7 @@ impl AppState {
self.entries = tree_view.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);
}

Expand All @@ -143,7 +143,7 @@ impl AppState {
self.entries = tree_view.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);
}

Expand Down Expand Up @@ -333,7 +333,7 @@ impl AppState {
self.entries = tree_view.sorted_entries(
self.navigation().view_root,
self.sorting,
self.scan.is_some(),
self.entry_check(),
);
}

Expand All @@ -353,7 +353,7 @@ impl AppState {

pub fn go_to_root(&mut self, tree_view: &TreeView<'_>) {
let root = self.navigation().tree_root;
let entries = tree_view.sorted_entries(root, self.sorting, self.scan.is_some());
let entries = tree_view.sorted_entries(root, self.sorting, self.entry_check());
self.navigation_mut().exit_node(root, &entries);
self.entries = entries;
}
Expand Down
3 changes: 3 additions & 0 deletions src/interactive/app/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub struct AppState {
pub walk_options: WalkOptions,
/// The paths used in the initial traversal, at least 1.
pub root_paths: Vec<PathBuf>,
/// If true, listed entries will be validated for presence when switching directories.
pub allow_entry_check: bool,
}

impl AppState {
Expand All @@ -61,6 +63,7 @@ impl AppState {
stats: TraversalStats::default(),
walk_options,
root_paths: input,
allow_entry_check: true,
}
}
}
5 changes: 4 additions & 1 deletion src/interactive/app/terminal.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::path::PathBuf;

use crate::interactive::EntryCheck;
use anyhow::Result;
use crossbeam::channel::Receiver;
use crosstermion::input::Event;
Expand Down Expand Up @@ -28,6 +29,7 @@ impl TerminalApp {
terminal: &mut Terminal<B>,
walk_options: WalkOptions,
byte_format: ByteFormat,
entry_check: bool,
input: Vec<PathBuf>,
) -> Result<TerminalApp>
where
Expand All @@ -40,6 +42,7 @@ impl TerminalApp {
let window = MainWindow::default();

let mut state = AppState::new(walk_options, input);
state.allow_entry_check = entry_check;
let traversal = Traversal::new();
let stats = TraversalStats::default();

Expand All @@ -49,7 +52,7 @@ impl TerminalApp {
state.navigation().view_root,
state.sorting,
state.glob_root(),
state.scan.is_some(),
EntryCheck::new(state.scan.is_some(), state.allow_entry_check),
);
state.navigation_mut().selected = state.entries.first().map(|b| b.index);

Expand Down
9 changes: 7 additions & 2 deletions src/interactive/app/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,13 @@ pub fn initialized_app_and_terminal_with_closure(
let (_key_send, key_receive) = crossbeam::channel::bounded(0);
let input_paths = fixture_paths.iter().map(|c| convert(c.as_ref())).collect();

let mut app =
TerminalApp::initialize(&mut terminal, walk_options, ByteFormat::Metric, input_paths)?;
let mut app = TerminalApp::initialize(
&mut terminal,
walk_options,
ByteFormat::Metric,
false, /* entry-check */
input_paths,
)?;
app.traverse()?;
app.run_until_traversed(&mut terminal, key_receive)?;

Expand Down
6 changes: 3 additions & 3 deletions src/interactive/app/tree_view.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{sorted_entries, EntryDataBundle, SortMode};
use crate::interactive::path_of;
use crate::interactive::{path_of, EntryCheck};
use dua::traverse::{EntryData, Traversal, Tree, TreeIndex};
use petgraph::{visit::Bfs, Direction};
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -50,14 +50,14 @@ impl TreeView<'_> {
&self,
view_root: TreeIndex,
sorting: SortMode,
is_scanning: bool,
check: EntryCheck,
) -> Vec<EntryDataBundle> {
sorted_entries(
&self.traversal.tree,
view_root,
sorting,
self.glob_tree_root,
is_scanning,
check,
)
}

Expand Down
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ fn main() -> Result<()> {

let res = match opt.command {
#[cfg(feature = "tui-crossplatform")]
Some(Interactive { input }) => {
Some(Interactive {
no_entry_check,
input,
}) => {
use anyhow::{anyhow, Context};
use crosstermion::terminal::{tui::new_terminal, AlternateRawScreen};

Expand All @@ -81,6 +84,7 @@ fn main() -> Result<()> {
&mut terminal,
walk_options,
byte_format,
!no_entry_check,
extract_paths_maybe_set_cwd(input, !opt.stay_on_filesystem)?,
)?;
app.traverse()?;
Expand Down
3 changes: 3 additions & 0 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ pub enum Command {
#[cfg(feature = "tui-crossplatform")]
#[clap(name = "interactive", visible_alias = "i")]
Interactive {
/// Do not check entries for presence when listing a directory to avoid slugging performance on slow filesystems.
#[clap(long, short = 'e')]
no_entry_check: bool,
/// One or more input files or directories. If unset, we will use all entries in the current working directory.
#[clap(value_parser)]
input: Vec<PathBuf>,
Expand Down

0 comments on commit d837d72

Please sign in to comment.