Skip to content

feat(dir): support path-restricted directory diffs#435

Open
dwf wants to merge 1 commit into
esmuellert:mainfrom
dwf:feat/dir-mode-path-filter
Open

feat(dir): support path-restricted directory diffs#435
dwf wants to merge 1 commit into
esmuellert:mainfrom
dwf:feat/dir-mode-path-filter

Conversation

@dwf

@dwf dwf commented Jul 10, 2026

Copy link
Copy Markdown

Motivation: comparing two very large directory trees where the set of created/deleted/modified files is already known ahead of time. The existing dir mode scans both trees exhaustively (recursive fs_scandir + content comparison), which is prohibitively expensive when the trees are huge and only a handful of paths are of interest -- the scan dominates, even though almost every file is identical or irrelevant.

Add an optional opts.paths list to dir mode so the diff can be restricted to a specific set of relative paths instead of walking the trees. Each listed path is stat'd directly in both roots (O(#paths) rather than O(tree)), so the cost scales with the paths you care about, not the size of the trees.

Classification per path: present on both -> content-compared (M/none); present on one side -> creation/deletion (A/D); absent on both -> reported via a new missing list and skipped. Paths are normalized (separator, leading ./ and /, de-duplicated).

The filter is threaded through explorer_data -> panel -> render -> refresh so refreshing the explorer (R) re-diffs only the listed paths.

Surface it via a new Lua API, require("codediff").dir_diff(dir1, dir2, { paths, layout }): a caller-supplied path list is unwieldy as inline :CodeDiff command arguments (it can be hundreds of entries), so a Lua entry point is the most ergonomic option for programmatic use. layout ("inline"/"side-by-side") is passed through to the existing dir-mode layout selection.

Motivation: comparing two very large directory trees where the set of
created/deleted/modified files is already known ahead of time. The
existing dir mode scans both trees exhaustively (recursive fs_scandir +
content comparison), which is prohibitively expensive when the trees are
huge and only a handful of paths are of interest -- the scan dominates,
even though almost every file is identical or irrelevant.

Add an optional `opts.paths` list to dir mode so the diff can be
restricted to a specific set of relative paths instead of walking the
trees. Each listed path is stat'd directly in both roots (O(#paths)
rather than O(tree)), so the cost scales with the paths you care about,
not the size of the trees.

Classification per path: present on both -> content-compared (M/none);
present on one side -> creation/deletion (A/D); absent on both -> reported
via a new `missing` list and skipped. Paths are normalized (separator,
leading `./` and `/`, de-duplicated).

The filter is threaded through explorer_data -> panel -> render -> refresh
so refreshing the explorer (R) re-diffs only the listed paths.

Surface it via a new Lua API, `require("codediff").dir_diff(dir1, dir2,
{ paths, layout })`: a caller-supplied path list is unwieldy as inline
`:CodeDiff` command arguments (it can be hundreds of entries), so a Lua
entry point is the most ergonomic option for programmatic use. `layout`
("inline"/"side-by-side") is passed through to the existing dir-mode
layout selection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dwf dwf force-pushed the feat/dir-mode-path-filter branch from fabf3c7 to 4bbb0e8 Compare July 10, 2026 22:25
@dwf

dwf commented Jul 10, 2026

Copy link
Copy Markdown
Author

N.B. Happy to revisit the public API or put it in e.g. a codediff.commands module.

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