feat: option to prevent cross-filesystem traversal#363
Merged
Conversation
Directories on different devices (mount points) were being traversed, leading to inaccurate usage reports and severe performance issues. Compare each entry's device ID against the root's device ID and treat cross-device directories as leaf nodes. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Instead of unconditionally skipping cross-device directories, make it opt-in via -x/--one-file-system (matching du convention). The default behavior now crosses device boundaries like du, dust, and dua. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Performance Regression Reportscommit: b00e32c There are no regressions. |
…tforms The `volume_serial_number()` API requires `windows_by_handle` which is an unstable library feature (rust-lang/rust#63010), so --one-file-system cannot be supported on Windows with stable Rust. Instead, return a RuntimeError::UnsupportedFeature(OneFileSystem) early and remove the Windows-specific device_id implementation. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a --one-file-system / -x option to keep traversal within the root filesystem (similar to du -x), wiring the flag through the CLI/app layers into FsTreeBuilder, and updating generated help/docs and tests accordingly.
Changes:
- Introduced filesystem device-id detection and used it in
FsTreeBuilderto skip descending into directories on other filesystems when enabled. - Added
--one-file-system/-xCLI flag and threaded it throughApp→Sub→FsTreeBuilder. - Updated tests and regenerated help/usage/completion exports to include the new option.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
src/fs_tree_builder.rs |
Adds one_file_system config and device-id checks during traversal. |
src/fs_tree_builder/device_id.rs |
New platform-gated device-id helper used by FsTreeBuilder. |
src/args.rs |
Adds --one-file-system / -x flag to CLI args (Unix-gated in help). |
src/app.rs |
Validates/threads the flag and rejects it on non-Unix builds. |
src/app/sub.rs |
Plumbs one_file_system into the FsTreeBuilder invocation. |
src/runtime_error.rs |
Adds UnsupportedFeature::OneFileSystem for non-Unix. |
tests/usual_cli.rs |
Updates FsTreeBuilder construction in CLI snapshot-style tests. |
tests/json.rs |
Updates FsTreeBuilder construction for JSON-related test. |
tests/cli_errors.rs |
Updates FsTreeBuilder construction for error-path tests. |
tests/_utils.rs |
Updates shared FsTreeBuilder helper construction used by tests. |
exports/short.help |
Regenerated short help including the new flag. |
exports/long.help |
Regenerated long help including the new flag. |
exports/completion.bash |
Regenerated bash completions including the new flag. |
exports/completion.zsh |
Regenerated zsh completions including the new flag. |
exports/completion.fish |
Regenerated fish completions including the new flag. |
exports/completion.ps1 |
Regenerated PowerShell completions including the new flag. |
exports/completion.elv |
Regenerated Elvish completions including the new flag. |
USAGE.md |
Regenerated usage docs including the new flag. |
README.md |
Removes prior limitation statement about not differentiating filesystems. |
The `#[clap(long)]` attribute on `one_file_system` already generates `--one-file-system`, so `visible_alias = "one-file-system"` was a duplicate causing doubled anchors in USAGE.md and redundant entries in shell completions. Regenerate all exports. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Unit tests in device_id.rs verify that get_device_id returns equal IDs for the same filesystem and different IDs across filesystems (/ vs /proc). Integration tests in one_file_system.rs: - same_device_on_sample_workspace: one_file_system=true produces the same tree as false when all files are on one device - cross_device_excludes_mount: uses unshare --user --mount --map-root-user to create a tmpfs mount inside a user namespace (no root required) and verifies -x excludes entries on the mounted filesystem https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
The different_filesystem_returns_different_ids unit test uses /proc (Linux-only) and /dev (macOS devfs), so split into two functions gated with #[cfg(target_os = "linux")] and #[cfg(target_os = "macos")]. The cross_device_excludes_mount integration test uses unshare which is Linux-only, so gate it with #[cfg(target_os = "linux")]. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
- Use `writeln!` to build the shell script instead of `format!` with inline braces, making the script construction clearer - Use `command_extra::CommandExtra` with `.with_args`/`.with_stdout`/ `.with_stderr` instead of bare `std::process` methods - Import `pretty_assertions::assert_eq` at module level https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
…tput Write each pdu invocation's output to a separate temp file, then emit them NUL-delimited with labels. Use find_section() to locate each section by label instead of splitting on '===' and indexing. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Replace the silent skip with a panic and actionable error message, matching the pattern from `fs_errors`. The test can be excluded via `RUSTFLAGS='--cfg pdu_test_skip_cross_device'`. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
The previous check only verified that `unshare --user --mount --map-root-user` succeeds, but not that tmpfs mounting is permitted inside the namespace. On systems where user namespaces work but unprivileged mounts are blocked, the test would fail instead of being caught by the probe. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
A bool discards the reason for failure. Return a Result with the stderr output from the probe command so the panic message includes actionable diagnostics (e.g. "unshare: unshare failed: Operation not permitted"). https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Replace the user-namespace-based (`unshare --user --mount`) cross-device test with a FUSE-based approach using `fuse2fs`. User namespaces are often disabled in CI containers, making the unshare test unreliable. The new test creates a small ext2 filesystem image, mounts it via `fuse2fs` (which only needs `/dev/fuse` and `fusermount`), and verifies that `pdu -x` correctly excludes entries on the mounted filesystem. Diagnostic messages clearly report which FUSE component is missing. The `--cfg pdu_test_skip_cross_device` skip flag is preserved. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
The `cross_device_excludes_mount` test requires `fuse2fs` (from e2fsprogs) and `fusermount3` (from fuse3) to mount an ext2 image via FUSE. Install these packages on Linux runners in both test.yaml and deploy.yaml so the test can run in CI without being skipped. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
054aa8f to
876739a
Compare
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Align with the existing naming convention used by `Direction::from_top_down` and `BarAlignment::from_align_right`. https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
3fab8d3 to
cfddd52
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #349.
This PR adds support for skipping directories on different filesystems, similar to the
-x/--one-file-systemflag found in tools likedu. This allows users to analyze disk usage within a single filesystem without counting mounted directories.https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6