disktree 0.2.0

Disk usage TUI: scan a drive, see what's taking space, and delete it safely
Documentation
# Changelog


All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.0] - 2026-07-26


### Added


- **MFT fast scan for elevated NTFS volumes.** Instead of one metadata read per
  directory, the whole volume's file table is read in a streaming pass. Used
  automatically when the volume is NTFS, the raw device is readable, and the
  target is the volume root; `--mft` forces it for a subdirectory and `--no-mft`
  disables it. Anything else falls back to the directory walk with a one-line
  explanation rather than an error.
- **Automatic elevation.** A whole-volume scan without privileges relaunches
  itself elevated in a new window, since a console process cannot gain
  privileges in place. `--no-elevate` opts out, and the relaunched process
  carries an internal flag so a failed probe cannot produce an elevation loop.
- `--mft-readers` for read concurrency during an MFT scan, defaulting to 8.
  Measured on the development NVMe drive, unbuffered 16 MiB reads scale 1774 →
  3613 MB/s from 1 to 8 concurrent readers and plateau there.
- `examples/mftprobe.rs`, a go/no-go check that runs the whole privileged
  sequence with no parser attached, so a failure names one API. Also reports
  bandwidth against concurrency.
- `examples/iocal.rs`, which calibrates read concurrency on any machine without
  needing elevation, and `examples/crosscheck.rs`, which scans a subtree both
  ways and diffs every shared directory.
- `--threads`/`-j` to set the number of concurrent directory reads.
- `examples/bench.rs`, a scan benchmark reporting files/s and dirs/s, with a
  `--split` mode for A/B comparisons against a single-use cold cache.
- `examples/probe.rs`, which reports which volume access masks and USN ioctls the
  current privilege level allows.
- Crate-level documentation with a running doctest, docs for the whole `index`
  API, and a README section explaining exactly what the reported sizes include.

### Correctness


The MFT parser's size and structure logic is pure functions over byte slices,
covered by 17 tests driving synthetic records. Two of the cases fail silently if
got wrong and are worth naming: resident `$DATA` must be sized from the
attribute's value length, or every small file — most files by count — reports
zero bytes; and `$ATTRIBUTE_LIST` spillover must be merged into the base record,
or the largest fragmented files report zero. Also covered: DOS 8.3 aliases
deduplicated, continuation extents ignored, alternate streams excluded, torn
reads and `BAAD` records rejected, malformed attribute chains terminating,
random bytes never panicking, and stale or missing parent references attaching
to an orphan container rather than to a recycled directory slot.

Validated against the directory walk on a real volume: 8,680 directories present
in both scanners, all 8,680 byte-for-byte identical, 100.00% agreement, no
orphaned records. A full 2 TB volume with 5.54M files scans in 10-21 s, against
41 s for a cold walk of a single 1.6M-file subtree.

The two scanners do not always report identical totals, by design. Hard-linked
files are counted once per link by the walk and once in total by the MFT, so the
walk reports more for trees like `C:\Windows`. `crosscheck` quantifies the delta.

### Fixed


- **The declared MSRV was wrong and the crate did not build on it.** `0.1.0`
  declared `rust-version = "1.85"` but used `is_multiple_of` (stable in 1.87)
  and let-chains (stable in 1.88), so anyone on 1.85 or 1.86 passed cargo's
  version check and then hit a compile error. The declared minimum is now 1.88
  and is verified against that toolchain.
- **Symlinks, junctions, and volume mount points vanished from the tree.** They
  were skipped entirely rather than recorded, so a volume mounted into a scanned
  directory was absent instead of showing as empty, and file counts undercounted.
  They now appear as zero-byte entries and are still never traversed.
- **A failed metadata read was reported as a zero-byte file.** It now counts
  toward the unreadable total the header displays.
- **The delete confirmation could not be acted on safely.** It listed bare names,
  so marking three unrelated `bin` folders read as "bin, bin, bin". It now shows
  full paths.
- **A partly completed delete left every ancestor overstating its size.**
  `remove_dir_all` can delete most of a tree before hitting an open file, and the
  Recycle Bin can accept some items and abort others; only the success path
  reconciled the tree. Failures are now re-checked on disk, and totals known to
  be stale say so.
- **Deleting something already gone reported freed bytes that were never freed.**
  Targets are re-checked immediately before deletion, since the tree can be
  minutes old.
- Recycle Bin quota failures reported the unhelpful "Some operations were
  aborted"; they now say what happened and suggest permanent deletion.
- Off Windows, running with no arguments failed with `'C:\' is not a directory`.
  The default root is now `/` there.

### Changed


- **Rendering cost no longer grows with directory size.** The table built one
  widget per child, which took roughly half a second per frame at 100,000
  entries — reachable today, since `C:\Windows\WinSxS\Manifests` holds tens of
  thousands. Only the visible rows are built now: measured 3.007 ms per frame at
  1,000 children versus 3.110 ms at 100,000.
- Directory enumeration runs on its own thread pool sized at twice the core
  count, leaving rayon's global pool for CPU-bound work. `--threads`/`-j`
  overrides it.
- Progress counters are published once per directory instead of once per file,
  and the displayed current path is sampled rather than formatted for every
  directory.

### Notes


`app` and `ui` are now `#[doc(hidden)]`. Their signatures name `ratatui` types,
so treating them as public API would make every `ratatui` release a breaking
change here. `index` and `mft` are the supported surface.

## [0.1.0] - 2026-07-26


Initial release: parallel directory scan with live progress, size-sorted
browser with percentage bars, and deletion to the Recycle Bin or permanently,
behind a confirmation.