mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 12:54:07 -07:00
fix(core): Respect user's .gitignore preference (#15482)
Co-authored-by: Gaurav <39389231+gsquared94@users.noreply.github.com>
This commit is contained in:
@@ -28,6 +28,10 @@ class MockConfig {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFileFilteringRespectGitIgnore() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
getFileFilteringRespectGeminiIgnore() {
|
getFileFilteringRespectGeminiIgnore() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ describe('RipGrepTool', () => {
|
|||||||
getTargetDir: () => tempRootDir,
|
getTargetDir: () => tempRootDir,
|
||||||
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
getFileFilteringRespectGeminiIgnore: () => true,
|
getFileFilteringRespectGeminiIgnore: () => true,
|
||||||
getFileFilteringOptions: () => ({
|
getFileFilteringOptions: () => ({
|
||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
@@ -277,6 +278,7 @@ describe('RipGrepTool', () => {
|
|||||||
getTargetDir: () => tempRootDir,
|
getTargetDir: () => tempRootDir,
|
||||||
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
getFileFilteringRespectGeminiIgnore: () => true,
|
getFileFilteringRespectGeminiIgnore: () => true,
|
||||||
getFileFilteringOptions: () => ({
|
getFileFilteringOptions: () => ({
|
||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
@@ -844,6 +846,7 @@ describe('RipGrepTool', () => {
|
|||||||
getWorkspaceContext: () =>
|
getWorkspaceContext: () =>
|
||||||
createMockWorkspaceContext(tempRootDir, [secondDir]),
|
createMockWorkspaceContext(tempRootDir, [secondDir]),
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
getFileFilteringRespectGeminiIgnore: () => true,
|
getFileFilteringRespectGeminiIgnore: () => true,
|
||||||
getFileFilteringOptions: () => ({
|
getFileFilteringOptions: () => ({
|
||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
@@ -956,6 +959,7 @@ describe('RipGrepTool', () => {
|
|||||||
getWorkspaceContext: () =>
|
getWorkspaceContext: () =>
|
||||||
createMockWorkspaceContext(tempRootDir, [secondDir]),
|
createMockWorkspaceContext(tempRootDir, [secondDir]),
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
getFileFilteringRespectGeminiIgnore: () => true,
|
getFileFilteringRespectGeminiIgnore: () => true,
|
||||||
getFileFilteringOptions: () => ({
|
getFileFilteringOptions: () => ({
|
||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
@@ -1477,6 +1481,70 @@ describe('RipGrepTool', () => {
|
|||||||
expect(result.llmContent).toContain('L1: secret log entry');
|
expect(result.llmContent).toContain('L1: secret log entry');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should disable gitignore rules when respectGitIgnore is false', async () => {
|
||||||
|
const configWithoutGitIgnore = {
|
||||||
|
getTargetDir: () => tempRootDir,
|
||||||
|
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
||||||
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => false,
|
||||||
|
getFileFilteringRespectGeminiIgnore: () => true,
|
||||||
|
getFileFilteringOptions: () => ({
|
||||||
|
respectGitIgnore: false,
|
||||||
|
respectGeminiIgnore: true,
|
||||||
|
}),
|
||||||
|
storage: {
|
||||||
|
getProjectTempDir: vi.fn().mockReturnValue('/tmp/project'),
|
||||||
|
},
|
||||||
|
isPathAllowed(this: Config, absolutePath: string): boolean {
|
||||||
|
const workspaceContext = this.getWorkspaceContext();
|
||||||
|
if (workspaceContext.isPathWithinWorkspace(absolutePath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectTempDir = this.storage.getProjectTempDir();
|
||||||
|
return isSubpath(path.resolve(projectTempDir), absolutePath);
|
||||||
|
},
|
||||||
|
validatePathAccess(this: Config, absolutePath: string): string | null {
|
||||||
|
if (this.isPathAllowed(absolutePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const workspaceDirs = this.getWorkspaceContext().getDirectories();
|
||||||
|
const projectTempDir = this.storage.getProjectTempDir();
|
||||||
|
return `Path not in workspace: Attempted path "${absolutePath}" resolves outside the allowed workspace directories: ${workspaceDirs.join(', ')} or the project temp directory: ${projectTempDir}`;
|
||||||
|
},
|
||||||
|
} as unknown as Config;
|
||||||
|
const gitIgnoreDisabledTool = new RipGrepTool(
|
||||||
|
configWithoutGitIgnore,
|
||||||
|
createMockMessageBus(),
|
||||||
|
);
|
||||||
|
|
||||||
|
mockSpawn.mockImplementationOnce(
|
||||||
|
createMockSpawn({
|
||||||
|
outputData:
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'match',
|
||||||
|
data: {
|
||||||
|
path: { text: 'ignored.log' },
|
||||||
|
line_number: 1,
|
||||||
|
lines: { text: 'secret log entry\n' },
|
||||||
|
},
|
||||||
|
}) + '\n',
|
||||||
|
exitCode: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const params: RipGrepToolParams = { pattern: 'secret' };
|
||||||
|
const invocation = gitIgnoreDisabledTool.build(params);
|
||||||
|
await invocation.execute(abortSignal);
|
||||||
|
|
||||||
|
expect(mockSpawn).toHaveBeenLastCalledWith(
|
||||||
|
expect.anything(),
|
||||||
|
expect.arrayContaining(['--no-ignore-vcs', '--no-ignore-exclude']),
|
||||||
|
expect.anything(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should add .geminiignore when enabled and patterns exist', async () => {
|
it('should add .geminiignore when enabled and patterns exist', async () => {
|
||||||
const geminiIgnorePath = path.join(tempRootDir, GEMINI_IGNORE_FILE_NAME);
|
const geminiIgnorePath = path.join(tempRootDir, GEMINI_IGNORE_FILE_NAME);
|
||||||
await fs.writeFile(geminiIgnorePath, 'ignored.log');
|
await fs.writeFile(geminiIgnorePath, 'ignored.log');
|
||||||
@@ -1484,6 +1552,7 @@ describe('RipGrepTool', () => {
|
|||||||
getTargetDir: () => tempRootDir,
|
getTargetDir: () => tempRootDir,
|
||||||
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
getFileFilteringRespectGeminiIgnore: () => true,
|
getFileFilteringRespectGeminiIgnore: () => true,
|
||||||
getFileFilteringOptions: () => ({
|
getFileFilteringOptions: () => ({
|
||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
@@ -1549,6 +1618,7 @@ describe('RipGrepTool', () => {
|
|||||||
getTargetDir: () => tempRootDir,
|
getTargetDir: () => tempRootDir,
|
||||||
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
getWorkspaceContext: () => createMockWorkspaceContext(tempRootDir),
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getFileFilteringRespectGitIgnore: () => true,
|
||||||
getFileFilteringRespectGeminiIgnore: () => false,
|
getFileFilteringRespectGeminiIgnore: () => false,
|
||||||
getFileFilteringOptions: () => ({
|
getFileFilteringOptions: () => ({
|
||||||
respectGitIgnore: true,
|
respectGitIgnore: true,
|
||||||
|
|||||||
@@ -366,6 +366,10 @@ class GrepToolInvocation extends BaseToolInvocation<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!no_ignore) {
|
if (!no_ignore) {
|
||||||
|
if (!this.config.getFileFilteringRespectGitIgnore()) {
|
||||||
|
rgArgs.push('--no-ignore-vcs', '--no-ignore-exclude');
|
||||||
|
}
|
||||||
|
|
||||||
const fileExclusions = new FileExclusions(this.config);
|
const fileExclusions = new FileExclusions(this.config);
|
||||||
const excludes = fileExclusions.getGlobExcludes([
|
const excludes = fileExclusions.getGlobExcludes([
|
||||||
...COMMON_DIRECTORY_EXCLUDES,
|
...COMMON_DIRECTORY_EXCLUDES,
|
||||||
|
|||||||
Reference in New Issue
Block a user