Add support for an additional exclusion file besides .gitignore and .geminiignore (#16487)

Co-authored-by: Adam Weidman <adamfweidman@google.com>
This commit is contained in:
Alisa
2026-01-27 17:19:13 -08:00
committed by GitHub
parent 18efe82ddc
commit adc8e11bb1
40 changed files with 1394 additions and 612 deletions
+50
View File
@@ -13,6 +13,7 @@ import { debugLogger } from '../utils/debugLogger.js';
import { ApprovalMode } from '../policy/types.js';
import type { HookDefinition } from '../hooks/types.js';
import { HookType, HookEventName } from '../hooks/types.js';
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
import * as path from 'node:path';
import * as fs from 'node:fs';
import { setGeminiMdFilename as mockSetGeminiMdFilename } from '../tools/memoryTool.js';
@@ -138,6 +139,8 @@ vi.mock('../services/gitService.js', () => {
return { GitService: GitServiceMock };
});
vi.mock('../services/fileDiscoveryService.js');
vi.mock('../ide/ide-client.js', () => ({
IdeClient: {
getInstance: vi.fn().mockResolvedValue({
@@ -623,6 +626,30 @@ describe('Server Config (config.ts)', () => {
expect(config.getFileFilteringRespectGitIgnore()).toBe(false);
});
it('should set customIgnoreFilePaths from params', () => {
const params: ConfigParameters = {
...baseParams,
fileFiltering: {
customIgnoreFilePaths: ['/path/to/ignore/file'],
},
};
const config = new Config(params);
expect(config.getCustomIgnoreFilePaths()).toStrictEqual([
'/path/to/ignore/file',
]);
});
it('should set customIgnoreFilePaths to empty array if not provided', () => {
const params: ConfigParameters = {
...baseParams,
fileFiltering: {
respectGitIgnore: true,
},
};
const config = new Config(params);
expect(config.getCustomIgnoreFilePaths()).toStrictEqual([]);
});
it('should initialize WorkspaceContext with includeDirectories', () => {
const includeDirectories = ['dir1', 'dir2'];
const paramsWithIncludeDirs: ConfigParameters = {
@@ -699,6 +726,29 @@ describe('Server Config (config.ts)', () => {
expect(fileService).toBeDefined();
});
it('should pass file filtering options to FileDiscoveryService', () => {
const configParams = {
...baseParams,
fileFiltering: {
respectGitIgnore: false,
respectGeminiIgnore: false,
customIgnoreFilePaths: ['.myignore'],
},
};
const config = new Config(configParams);
config.getFileService();
expect(FileDiscoveryService).toHaveBeenCalledWith(
path.resolve(TARGET_DIR),
{
respectGitIgnore: false,
respectGeminiIgnore: false,
customIgnoreFilePaths: ['.myignore'],
},
);
});
describe('Usage Statistics', () => {
it('defaults usage statistics to enabled if not specified', () => {
const config = new Config({
+14 -1
View File
@@ -328,6 +328,7 @@ export interface ConfigParameters {
enableFuzzySearch?: boolean;
maxFileCount?: number;
searchTimeout?: number;
customIgnoreFilePaths?: string[];
};
checkpointing?: boolean;
proxy?: string;
@@ -465,6 +466,7 @@ export class Config {
enableFuzzySearch: boolean;
maxFileCount: number;
searchTimeout: number;
customIgnoreFilePaths: string[];
};
private fileDiscoveryService: FileDiscoveryService | null = null;
private gitService: GitService | undefined = undefined;
@@ -631,6 +633,7 @@ export class Config {
params.fileFiltering?.searchTimeout ??
DEFAULT_FILE_FILTERING_OPTIONS.searchTimeout ??
5000,
customIgnoreFilePaths: params.fileFiltering?.customIgnoreFilePaths ?? [],
};
this.checkpointing = params.checkpointing ?? false;
this.proxy = params.proxy;
@@ -1528,16 +1531,22 @@ export class Config {
getFileFilteringRespectGitIgnore(): boolean {
return this.fileFiltering.respectGitIgnore;
}
getFileFilteringRespectGeminiIgnore(): boolean {
return this.fileFiltering.respectGeminiIgnore;
}
getCustomIgnoreFilePaths(): string[] {
return this.fileFiltering.customIgnoreFilePaths;
}
getFileFilteringOptions(): FileFilteringOptions {
return {
respectGitIgnore: this.fileFiltering.respectGitIgnore,
respectGeminiIgnore: this.fileFiltering.respectGeminiIgnore,
maxFileCount: this.fileFiltering.maxFileCount,
searchTimeout: this.fileFiltering.searchTimeout,
customIgnoreFilePaths: this.fileFiltering.customIgnoreFilePaths,
};
}
@@ -1574,7 +1583,11 @@ export class Config {
getFileService(): FileDiscoveryService {
if (!this.fileDiscoveryService) {
this.fileDiscoveryService = new FileDiscoveryService(this.targetDir);
this.fileDiscoveryService = new FileDiscoveryService(this.targetDir, {
respectGitIgnore: this.fileFiltering.respectGitIgnore,
respectGeminiIgnore: this.fileFiltering.respectGeminiIgnore,
customIgnoreFilePaths: this.fileFiltering.customIgnoreFilePaths,
});
}
return this.fileDiscoveryService;
}
+6
View File
@@ -9,6 +9,7 @@ export interface FileFilteringOptions {
respectGeminiIgnore: boolean;
maxFileCount?: number;
searchTimeout?: number;
customIgnoreFilePaths: string[];
}
// For memory files
@@ -17,6 +18,7 @@ export const DEFAULT_MEMORY_FILE_FILTERING_OPTIONS: FileFilteringOptions = {
respectGeminiIgnore: true,
maxFileCount: 20000,
searchTimeout: 5000,
customIgnoreFilePaths: [],
};
// For all other files
@@ -25,4 +27,8 @@ export const DEFAULT_FILE_FILTERING_OPTIONS: FileFilteringOptions = {
respectGeminiIgnore: true,
maxFileCount: 20000,
searchTimeout: 5000,
customIgnoreFilePaths: [],
};
// Generic exclusion file name
export const GEMINI_IGNORE_FILE_NAME = '.geminiignore';