Introduce GEMINI_CLI_HOME for strict test isolation (#15907)

This commit is contained in:
N. Taylor Mullen
2026-01-06 20:09:39 -08:00
committed by GitHub
parent a26463b056
commit 7956eb239e
54 changed files with 455 additions and 148 deletions

View File

@@ -11,7 +11,7 @@ import * as fs from 'node:fs';
import * as os from 'node:os';
import path from 'node:path';
import { randomUUID } from 'node:crypto';
import { GEMINI_DIR } from './paths.js';
import { GEMINI_DIR, homedir as pathsHomedir } from './paths.js';
import { debugLogger } from './debugLogger.js';
vi.mock('node:fs', async (importOriginal) => {
@@ -23,22 +23,30 @@ vi.mock('node:fs', async (importOriginal) => {
} as typeof actual;
});
vi.mock('os', async (importOriginal) => {
const os = await importOriginal<typeof import('os')>();
vi.mock('node:os', async (importOriginal) => {
const os = await importOriginal<typeof import('node:os')>();
return {
...os,
homedir: vi.fn(),
};
});
vi.mock('crypto', async (importOriginal) => {
const crypto = await importOriginal<typeof import('crypto')>();
vi.mock('node:crypto', async (importOriginal) => {
const crypto = await importOriginal<typeof import('node:crypto')>();
return {
...crypto,
randomUUID: vi.fn(),
};
});
vi.mock('./paths.js', async (importOriginal) => {
const actual = await importOriginal<typeof import('./paths.js')>();
return {
...actual,
homedir: vi.fn(),
};
});
describe('InstallationManager', () => {
let tempHomeDir: string;
let installationManager: InstallationManager;
@@ -49,6 +57,7 @@ describe('InstallationManager', () => {
tempHomeDir = fs.mkdtempSync(
path.join(os.tmpdir(), 'gemini-cli-test-home-'),
);
(pathsHomedir as Mock).mockReturnValue(tempHomeDir);
(os.homedir as Mock).mockReturnValue(tempHomeDir);
installationManager = new InstallationManager();
});

View File

@@ -35,6 +35,16 @@ vi.mock('os', async (importOriginal) => {
};
});
vi.mock('../utils/paths.js', async (importOriginal) => {
const actual = await importOriginal<typeof import('../utils/paths.js')>();
return {
...actual,
homedir: vi.fn(),
};
});
import { homedir as pathsHomedir } from './paths.js';
describe('memoryDiscovery', () => {
const DEFAULT_FOLDER_TRUST = true;
let testRootDir: string;
@@ -67,6 +77,7 @@ describe('memoryDiscovery', () => {
cwd = await createEmptyDir(path.join(projectRoot, 'src'));
homedir = await createEmptyDir(path.join(testRootDir, 'userhome'));
vi.mocked(os.homedir).mockReturnValue(homedir);
vi.mocked(pathsHomedir).mockReturnValue(homedir);
});
afterEach(async () => {

View File

@@ -7,14 +7,13 @@
import * as fs from 'node:fs/promises';
import * as fsSync from 'node:fs';
import * as path from 'node:path';
import { homedir } from 'node:os';
import { bfsFileSearch } from './bfsFileSearch.js';
import { getAllGeminiMdFilenames } from '../tools/memoryTool.js';
import type { FileDiscoveryService } from '../services/fileDiscoveryService.js';
import { processImports } from './memoryImportProcessor.js';
import type { FileFilteringOptions } from '../config/constants.js';
import { DEFAULT_MEMORY_FILE_FILTERING_OPTIONS } from '../config/constants.js';
import { GEMINI_DIR } from './paths.js';
import { GEMINI_DIR, homedir } from './paths.js';
import type { ExtensionLoader } from './extensionLoader.js';
import { debugLogger } from './debugLogger.js';
import type { Config } from '../config/config.js';

View File

@@ -6,6 +6,7 @@
import path from 'node:path';
import os from 'node:os';
import process from 'node:process';
import * as crypto from 'node:crypto';
export const GEMINI_DIR = '.gemini';
@@ -18,13 +19,33 @@ export const GOOGLE_ACCOUNTS_FILENAME = 'google_accounts.json';
*/
export const SHELL_SPECIAL_CHARS = /[ \t()[\]{};|*?$`'"#&<>!~]/;
/**
* Returns the home directory.
* If GEMINI_CLI_HOME environment variable is set, it returns its value.
* Otherwise, it returns the user's home directory.
*/
export function homedir(): string {
const envHome = process.env['GEMINI_CLI_HOME'];
if (envHome) {
return envHome;
}
return os.homedir();
}
/**
* Returns the operating system's default directory for temporary files.
*/
export function tmpdir(): string {
return os.tmpdir();
}
/**
* Replaces the home directory with a tilde.
* @param path - The path to tildeify.
* @returns The tildeified path.
*/
export function tildeifyPath(path: string): string {
const homeDir = os.homedir();
const homeDir = homedir();
if (path.startsWith(homeDir)) {
return path.replace(homeDir, '~');
}

View File

@@ -10,13 +10,13 @@ import { UserAccountManager } from './userAccountManager.js';
import * as fs from 'node:fs';
import * as os from 'node:os';
import path from 'node:path';
import { GEMINI_DIR } from './paths.js';
import { GEMINI_DIR, homedir as pathsHomedir } from './paths.js';
import { debugLogger } from './debugLogger.js';
vi.mock('os', async (importOriginal) => {
const os = await importOriginal<typeof import('os')>();
vi.mock('./paths.js', async (importOriginal) => {
const actual = await importOriginal<typeof import('./paths.js')>();
return {
...os,
...actual,
homedir: vi.fn(),
};
});
@@ -30,7 +30,7 @@ describe('UserAccountManager', () => {
tempHomeDir = fs.mkdtempSync(
path.join(os.tmpdir(), 'gemini-cli-test-home-'),
);
(os.homedir as Mock).mockReturnValue(tempHomeDir);
(pathsHomedir as Mock).mockReturnValue(tempHomeDir);
accountsFile = () =>
path.join(tempHomeDir, GEMINI_DIR, 'google_accounts.json');
userAccountManager = new UserAccountManager();