diff options
| author | Ben Sima <ben@bsima.me> | 2025-11-14 18:55:02 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bsima.me> | 2025-11-14 18:55:02 -0500 |
| commit | f6cd87b7544628f8947fb63907f6f5fee479c9cd (patch) | |
| tree | 64d24a8a8f3f34e7c18c53662a7e1bea875a9f66 /Omni/Bild | |
| parent | 2558312e1de98356597e2df3b0d2945499ccd86a (diff) | |
Tighten Nix source filtering to prevent spurious rebuilds
Only include directories that are ancestors of source files in
allSources. Previously accepted all directories, causing rebuilds
when any new directory was added to the repo.
Implementation: - Precompute normalized source paths and their ancestor
directories - Filter directories against allowedDirs whitelist -
Normalize paths in file filter for consistency - Keep existing skip
list behavior for _ and .direnv
This is optimization #2 from Phase 2 of the performance plan.
Diffstat (limited to 'Omni/Bild')
| -rw-r--r-- | Omni/Bild/Builder.nix | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/Omni/Bild/Builder.nix b/Omni/Bild/Builder.nix index 6731185..2d311ff 100644 --- a/Omni/Bild/Builder.nix +++ b/Omni/Bild/Builder.nix @@ -32,20 +32,51 @@ with bild; let isEmpty = x: x == null || x == []; skip = ["_" ".direnv"]; + + # Normalize paths by removing leading "./" + normalize = p: lib.strings.removePrefix "./" p; + + # Given a list of path parts, produce all cumulative prefixes: + # ["a","b","c"] -> ["a","a/b","a/b/c"] + dirPrefixes = parts: + if parts == [] + then [] + else let + hd = lib.lists.head parts; + tl = lib.lists.tail parts; + rest = dirPrefixes tl; + in + [hd] ++ (lib.lists.map (r: "${hd}/${r}") rest); + + # Normalize all source file paths (relative to root) + allSourcesRel = lib.lists.map normalize allSources; + + # Allowed directories are the ancestors of all source files, plus the repo root "" + allowedDirs = lib.lists.unique ( + [""] + ++ lib.lists.concatMap + (p: let + parts = lib.strings.splitString "/" p; + in + dirPrefixes (lib.lists.init parts)) + allSourcesRel + ); + filter = file: type: if lib.lists.elem (builtins.baseNameOf file) skip then false - # TODO: this means any new directory will cause a rebuild. this bad. i - # should recurse into the directory and match against the srcs. for now I - # just use preBuild to delete empty dirs else if type == "directory" - then true + then let + rel = lib.strings.removePrefix "${root}/" file; + rel' = normalize rel; + in + lib.lists.elem rel' allowedDirs else if type == "regular" - then - lib.trivial.pipe file [ - (f: lib.strings.removePrefix "${root}/" f) - (f: lib.lists.elem f allSources) - ] + then let + rel = lib.strings.removePrefix "${root}/" file; + rel' = normalize rel; + in + lib.lists.elem rel' allSourcesRel else false; # remove empty directories, leftover from the src filter |
