Skip to content

Cut per-frame work in the explore screen, and harden the git probe, link guard and file-table reader - #84

Open
armada45-pixel wants to merge 3 commits into
tobi:mainfrom
armada45-pixel:perf-and-hardening
Open

armada45-pixel wants to merge 3 commits into
tobi:mainfrom
armada45-pixel:perf-and-hardening

Conversation

@armada45-pixel

@armada45-pixel armada45-pixel commented Oct 12, 2026 •

Copy link
Copy Markdown

Three commits, each reviewable on its own. None of this overlaps #80, #81 or #82 as far as I can tell; where it came close (a mark on a name that is not Unicode) I left it to #82.

Performance

  • Switching Size / Files re-ranks the tree in place (Arc::make_mut) instead of deep-cloning it first. On a whole disk that clone is tens of millions of nodes.
  • Each frame builds label strings only for the 150 labels it will draw: slots are collected by reference, sorted by area, truncated, and only then formatted. The set of marked crumbs is cached until the marks or the tree change (Marks gets a generation counter).
  • The sibling menu ranks (index, value) pairs and names only the 24 rows it shows.
  • Layout picks the kept children with select_nth_unstable_by and sorts only those, instead of sorting every child of a directory with 100k entries to keep 96.
  • The free-space ticker calls space_info on the background executor. A network or sleeping drive can take seconds, and that was the UI thread.

Fixes

  • Node::find takes from the front of a VecDeque. Popping the back of a Vec searched depth-first, so a deep match in a late branch could be found before a shallow one.
  • Shift-scroll panning is clamped, like every other way of moving the view; it could push the mosaic off screen.
  • Byte totals use saturating_add. The release profile has overflow-checks = true, so a wrapped sum was a panic.

Hardening

  • git probe: GIT_ALLOW_PROTOCOL=none. With GIT_NO_LAZY_FETCH already set this is a second lock on the same door: a scanned checkout's config must not be able to name a transport for git to run. The Unix test with an ext:: promisor remote passes on git ≥ 2.44 with or without this line (lazy fetch is already off there); it is a regression guard, not a proof.
  • removal::linked: when a path's real location cannot be read but its parent is still there, the path is refused instead of passed. Before, a failed canonicalize was treated as "nothing to compare", which fails open.
  • mft.rs: bounds for a crafted volume — attribute-list records are capped, a table whose runs are shorter than it claims is refused, and a directory cycle stops the walk so the scan falls back to the ordinary one.
  • release.yml: actions pinned to SHAs, persist-credentials: false, and the macOS signing secrets moved from job-level env to the two steps that use them. Not exercised: I cannot run the release workflow, so this one needs a careful look, or drop the commit.

Testing

Windows 11, Rust 1.97.1: cargo xtask lint green, cargo xtask test green (68 app, 157 core, 1 ignored). Not run on Linux or macOS; the new git test is #[cfg(unix)] and so has only been compiled out here — CI will be its first run.

🤖 Generated with Claude Code

armada45-pixel and others added 3 commits October 13, 2026 06:56
Switching the metric re-ranks the tree in place instead of cloning it,
which on a whole disk is tens of millions of nodes copied to change an
order. A frame builds label text only for the tiles whose labels it will
draw, and reuses the set of marked crumbs until the marks or the tree
change. The sibling menu names only the rows it shows, layout picks its
kept children with a partial sort, and `Node::find` walks a real queue.

The free-space ticker asks the volume off the UI thread, since a network
or sleeping drive can take seconds to answer, and shift-scroll panning is
clamped like every other way of moving the view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The git probe sets GIT_ALLOW_PROTOCOL=none: a scanned checkout's own
configuration could otherwise name a transport for git to run while
disktree only meant to read its status.

The removal guard no longer passes a path whose real location cannot be
read while its parent is there to read; a link leading out of the scanned
root could hide behind that failure.

The NTFS file-table reader bounds what a crafted volume can make it do:
attribute-list records are capped, a table that claims more than its
runs hold is refused, and a directory graph with a cycle stops the walk
so the scan falls back to the ordinary one.

Byte totals saturate instead of overflowing; release builds check
overflow, so a wrapped sum was a panic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Actions are pinned to commit SHAs, checkouts keep no credentials, and the
macOS signing secrets reach only the two steps that use them instead of
every step of the job, the build's own scripts included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant