feat: add ignoreAdditionalDirs config to let repos extend IGNORE_DIRS#1666
Conversation
Impact: 4 functions changed, 8 affected
…1649 Impact: 1 functions changed, 5 affected
…1649 Impact: 3 functions changed, 8 affected
Add an `ignoreAdditionalDirs` key to `.codegraphrc.json` (array of strings) that is merged with the global IGNORE_DIRS set at file-collection time. This lets each repo declare its own carve-outs without baking them into the hardcoded global default. - Add `buildIgnoreSet(additionalDirs?)` helper to `shared/constants.ts` that merges IGNORE_DIRS with any extra dirs without mutating the original set - Add `ignoreAdditionalDirs: string[]` to `CodegraphConfig` in `types.ts` and `DEFAULTS` in `infrastructure/config.ts`; include it in `BUILD_HASH_KEYS` so config changes trigger a full rebuild - Update `collectFiles` in `builder/helpers.ts` to merge both `ignoreDirs` and `ignoreAdditionalDirs` into the walk's ignore set via `buildIgnoreSet` - Remove `crates` from the global IGNORE_DIRS default — it was added to handle NAPI-RS artifacts in this repo's Rust workspace, but silently excluded `crates/` in every other codebase; add `"ignoreAdditionalDirs": ["crates"]` to this repo's `.codegraphrc.json` instead Closes #1649 Impact: 6 functions changed, 2 affected
Greptile SummaryThis PR introduces
Confidence Score: 4/5Safe to merge for this repo given the existing The Rust BuildConfig was not updated to include ignore_additional_dirs, so ignoreAdditionalDirs values are silently discarded by the native engine. For this specific repo the exclude glob provides a workaround, but any other user relying on ignoreAdditionalDirs alone without a matching exclude will find those directories processed by the native engine — the feature is only half-implemented. crates/codegraph-core/src/infrastructure/config.rs and crates/codegraph-core/src/domain/graph/builder/pipeline.rs need an ignore_additional_dirs field and merge logic to match what the JS side does. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
RC[".codegraphrc.json\nignoreAdditionalDirs: ['crates']"] --> LC[loadConfig]
LC --> BGS["buildIgnoreSet(\n ignoreDirs + ignoreAdditionalDirs\n)"]
BGS --> IGN["ignoreSet\n(ReadonlySet)"]
IGN --> CF["collectFiles (JS/WASM)\nshouldSkipEntry checks ignoreSet"]
IGN --> WA["watcher.ts\ncollectTrackedFiles / shouldIgnorePath"]
subgraph "Native Engine path"
LC2["ctx.config (JSON)"] --> RBC["Rust BuildConfig\nonly reads ignoreDirs"]
RBC --> PL["pipeline.rs\ncollect_files(&config.ignore_dirs, ...)"]
PL --> MISS["ignoreAdditionalDirs\n⚠️ SILENTLY DROPPED"]
MISS --> EXCL["Fallback: exclude glob\n'crates/**' filters files\nbut dir is still traversed"]
end
LC --> LC2
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
RC[".codegraphrc.json\nignoreAdditionalDirs: ['crates']"] --> LC[loadConfig]
LC --> BGS["buildIgnoreSet(\n ignoreDirs + ignoreAdditionalDirs\n)"]
BGS --> IGN["ignoreSet\n(ReadonlySet)"]
IGN --> CF["collectFiles (JS/WASM)\nshouldSkipEntry checks ignoreSet"]
IGN --> WA["watcher.ts\ncollectTrackedFiles / shouldIgnorePath"]
subgraph "Native Engine path"
LC2["ctx.config (JSON)"] --> RBC["Rust BuildConfig\nonly reads ignoreDirs"]
RBC --> PL["pipeline.rs\ncollect_files(&config.ignore_dirs, ...)"]
PL --> MISS["ignoreAdditionalDirs\n⚠️ SILENTLY DROPPED"]
MISS --> EXCL["Fallback: exclude glob\n'crates/**' filters files\nbut dir is still traversed"]
end
LC --> LC2
Reviews (6): Last reviewed commit: "fix: resolve merge conflicts with main" | Re-trigger Greptile |
| try { | ||
| ctx.nativeDb.exec('PRAGMA foreign_keys = OFF'); | ||
| } catch { | ||
| // exec may not exist on very old addon versions — safe to ignore | ||
| } |
There was a problem hiding this comment.
PRAGMA foreign_keys = OFF is never re-enabled for this connection
openNativeDatabase (line 1893) returns early with if (ctx.nativeDb || !ctx.nativeAvailable) return, so the same connection is reused across incremental builds within the same PipelineContext lifetime. FK enforcement is disabled once here and remains OFF for all subsequent buildGraph() calls on that connection — not just for the first build. For older binaries this is the intended workaround, but for newer binaries (≥ v3.14) it silently discards any FK-level data-integrity signals they could otherwise surface. Adding an explicit ctx.nativeDb.exec('PRAGMA foreign_keys = ON') after buildGraph() returns would restore enforcement for follow-up operations without affecting the old-binary workaround.
There was a problem hiding this comment.
Fixed — added PRAGMA foreign_keys = ON immediately after buildGraph() returns (wrapped in the same try/catch for old addon versions). This restores FK enforcement for JS post-passes (CHA, dataflow, structure) without affecting the old-binary workaround during the Rust build phase.
| export function buildIgnoreSet(additionalDirs?: string[]): Set<string> { | ||
| if (!additionalDirs || additionalDirs.length === 0) return IGNORE_DIRS; | ||
| return new Set([...IGNORE_DIRS, ...additionalDirs]); | ||
| } |
There was a problem hiding this comment.
buildIgnoreSet returns a direct reference to the mutable global IGNORE_DIRS when no additional dirs are provided. Any caller that receives this return value and calls .add() or .delete() on it would mutate the shared global — a footgun that the current call sites avoid, but that future code could hit unexpectedly. Returning IGNORE_DIRS as ReadonlySet<string> communicates the aliasing intent in the type system.
| export function buildIgnoreSet(additionalDirs?: string[]): Set<string> { | |
| if (!additionalDirs || additionalDirs.length === 0) return IGNORE_DIRS; | |
| return new Set([...IGNORE_DIRS, ...additionalDirs]); | |
| } | |
| export function buildIgnoreSet(additionalDirs?: string[]): ReadonlySet<string> { | |
| if (!additionalDirs || additionalDirs.length === 0) return IGNORE_DIRS; | |
| return new Set([...IGNORE_DIRS, ...additionalDirs]); | |
| } |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Fixed — changed the return type of buildIgnoreSet to ReadonlySet<string> in constants.ts, and updated shouldSkipEntry and CollectContext.ignoreSet in helpers.ts to accept ReadonlySet<string> consistently. This prevents accidental mutation of the shared IGNORE_DIRS global through the no-extras fast path.
Codegraph Impact Analysis13 functions changed → 12 callers affected across 8 files
|
Prevents accidental mutation of the shared IGNORE_DIRS global when the caller receives a direct reference (the no-extras fast path). Update shouldSkipEntry and CollectContext.ignoreSet to accept ReadonlySet<string> consistently. Impact: 3 functions changed, 2 affected
FK enforcement is disabled before buildGraph() as a workaround for old-binary purge failures (< v3.14). Re-enable it immediately after buildGraph() returns so JS post-passes (CHA, dataflow, structure) run with full FK enforcement rather than inheriting the workaround. Impact: 1 functions changed, 5 affected
The watcher previously used the global IGNORE_DIRS directly via shouldIgnore(), so removing 'crates' from IGNORE_DIRS (the main change in this PR) caused the watcher to traverse and trigger rebuilds for files under crates/ — directly contradicting the ignoreAdditionalDirs exclusion that works correctly in batch builds via collectFiles. Fix: load .codegraphrc.json in setupWatcher, build the merged ignore set with buildIgnoreSet(ignoreDirs + ignoreAdditionalDirs), store it in WatcherContext, and thread it through collectTrackedFiles (polling mode) and shouldIgnorePath (native OS watcher mode). Both watcher paths now respect the same exclusion set as the batch build path. Impact: 6 functions changed, 4 affected
|
Fixed the watcher regression identified in the Greptile summary: |
docs check acknowledged
Summary
ignoreAdditionalDirs: string[]to.codegraphrc.json(andCodegraphConfig/DEFAULTS) — an array of additional directory names that are merged with the built-inIGNORE_DIRSset at file-collection timebuildIgnoreSet(additionalDirs?)helper toshared/constants.tsthat produces a merged ignore set without mutating the globalIGNORE_DIRScratesfrom the globalIGNORE_DIRSdefault (it was baking a repo-specific Rust workspace carve-out into every analysis); adds"ignoreAdditionalDirs": ["crates"]to this repo's own.codegraphrc.jsoninsteadignoreAdditionalDirsinBUILD_HASH_KEYSso changing the value triggers a full rebuildTest plan
npx vitest run tests/unit/constants.test.ts— new tests verifycratesis not inIGNORE_DIRS,buildIgnoreSetmerges correctly, and immutability is preservednpx vitest run tests/unit/builder.test.ts— new tests verifycollectFilesrespectsignoreAdditionalDirsalone and combined withignoreDirsnpm run lint— clean (no warnings)npx vitest run tests/unit/— 1137 tests passCloses #1649