diff options
| author | Yuki Okita <[email protected]> | 2025-08-20 10:55:47 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-08-20 01:55:47 +0000 |
| commit | 21c6480b65528a98ac0e1e3855f3c78c1f9b7cbe (patch) | |
| tree | 5555ec429209e87e0c21483c9e5fddd53ac01dbc /packages/cli/src/config | |
| parent | 1049d388451120587a8643a401fd71430a8cd5fe (diff) | |
Refac: Centralize storage file management (#4078)
Co-authored-by: Taylor Mullen <[email protected]>
Diffstat (limited to 'packages/cli/src/config')
| -rw-r--r-- | packages/cli/src/config/config.test.ts | 62 | ||||
| -rw-r--r-- | packages/cli/src/config/extension.test.ts | 3 | ||||
| -rw-r--r-- | packages/cli/src/config/extension.ts | 10 | ||||
| -rw-r--r-- | packages/cli/src/config/settings.ts | 18 |
4 files changed, 51 insertions, 42 deletions
diff --git a/packages/cli/src/config/config.test.ts b/packages/cli/src/config/config.test.ts index 727f6fe1..c9426379 100644 --- a/packages/cli/src/config/config.test.ts +++ b/packages/cli/src/config/config.test.ts @@ -6,7 +6,6 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import * as os from 'os'; -import * as fs from 'fs'; import * as path from 'path'; import { ShellTool, EditTool, WriteFileTool } from '@google/gemini-cli-core'; import { loadCliConfig, parseArguments } from './config.js'; @@ -19,6 +18,38 @@ vi.mock('./trustedFolders.js', () => ({ isWorkspaceTrusted: vi.fn(), })); +vi.mock('fs', async (importOriginal) => { + const actualFs = await importOriginal<typeof import('fs')>(); + const pathMod = await import('path'); + const mockHome = '/mock/home/user'; + const MOCK_CWD1 = process.cwd(); + const MOCK_CWD2 = pathMod.resolve(pathMod.sep, 'home', 'user', 'project'); + + const mockPaths = new Set([ + MOCK_CWD1, + MOCK_CWD2, + pathMod.resolve(pathMod.sep, 'cli', 'path1'), + pathMod.resolve(pathMod.sep, 'settings', 'path1'), + pathMod.join(mockHome, 'settings', 'path2'), + pathMod.join(MOCK_CWD2, 'cli', 'path2'), + pathMod.join(MOCK_CWD2, 'settings', 'path3'), + ]); + + return { + ...actualFs, + mkdirSync: vi.fn(), + writeFileSync: vi.fn(), + existsSync: vi.fn((p) => mockPaths.has(p.toString())), + statSync: vi.fn((p) => { + if (mockPaths.has(p.toString())) { + return { isDirectory: () => true } as unknown as import('fs').Stats; + } + return (actualFs as typeof import('fs')).statSync(p as unknown as string); + }), + realpathSync: vi.fn((p) => p), + }; +}); + vi.mock('os', async (importOriginal) => { const actualOs = await importOriginal<typeof os>(); return { @@ -1441,35 +1472,6 @@ describe('loadCliConfig folderTrust', () => { }); }); -vi.mock('fs', async () => { - const actualFs = await vi.importActual<typeof fs>('fs'); - const MOCK_CWD1 = process.cwd(); - const MOCK_CWD2 = path.resolve(path.sep, 'home', 'user', 'project'); - - const mockPaths = new Set([ - MOCK_CWD1, - MOCK_CWD2, - path.resolve(path.sep, 'cli', 'path1'), - path.resolve(path.sep, 'settings', 'path1'), - path.join(os.homedir(), 'settings', 'path2'), - path.join(MOCK_CWD2, 'cli', 'path2'), - path.join(MOCK_CWD2, 'settings', 'path3'), - ]); - - return { - ...actualFs, - existsSync: vi.fn((p) => mockPaths.has(p.toString())), - statSync: vi.fn((p) => { - if (mockPaths.has(p.toString())) { - return { isDirectory: () => true }; - } - // Fallback for other paths if needed, though the test should be specific. - return actualFs.statSync(p); - }), - realpathSync: vi.fn((p) => p), - }; -}); - describe('loadCliConfig with includeDirectories', () => { const originalArgv = process.argv; diff --git a/packages/cli/src/config/extension.test.ts b/packages/cli/src/config/extension.test.ts index 85852bd7..ece36916 100644 --- a/packages/cli/src/config/extension.test.ts +++ b/packages/cli/src/config/extension.test.ts @@ -10,7 +10,6 @@ import * as os from 'os'; import * as path from 'path'; import { EXTENSIONS_CONFIG_FILENAME, - EXTENSIONS_DIRECTORY_NAME, annotateActiveExtensions, loadExtensions, } from './extension.js'; @@ -23,6 +22,8 @@ vi.mock('os', async (importOriginal) => { }; }); +const EXTENSIONS_DIRECTORY_NAME = path.join('.gemini', 'extensions'); + describe('loadExtensions', () => { let tempWorkspaceDir: string; let tempHomeDir: string; diff --git a/packages/cli/src/config/extension.ts b/packages/cli/src/config/extension.ts index 1922f55a..46fd32fc 100644 --- a/packages/cli/src/config/extension.ts +++ b/packages/cli/src/config/extension.ts @@ -4,12 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { MCPServerConfig, GeminiCLIExtension } from '@google/gemini-cli-core'; +import { + MCPServerConfig, + GeminiCLIExtension, + Storage, +} from '@google/gemini-cli-core'; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; -export const EXTENSIONS_DIRECTORY_NAME = path.join('.gemini', 'extensions'); export const EXTENSIONS_CONFIG_FILENAME = 'gemini-extension.json'; export interface Extension { @@ -43,7 +46,8 @@ export function loadExtensions(workspaceDir: string): Extension[] { } function loadExtensionsFromDir(dir: string): Extension[] { - const extensionsDir = path.join(dir, EXTENSIONS_DIRECTORY_NAME); + const storage = new Storage(dir); + const extensionsDir = storage.getExtensionsDir(); if (!fs.existsSync(extensionsDir)) { return []; } diff --git a/packages/cli/src/config/settings.ts b/packages/cli/src/config/settings.ts index 414caf11..3df98d95 100644 --- a/packages/cli/src/config/settings.ts +++ b/packages/cli/src/config/settings.ts @@ -11,6 +11,7 @@ import * as dotenv from 'dotenv'; import { GEMINI_CONFIG_DIR as GEMINI_DIR, getErrorMessage, + Storage, } from '@google/gemini-cli-core'; import stripJsonComments from 'strip-json-comments'; import { DefaultLight } from '../ui/themes/default-light.js'; @@ -20,8 +21,9 @@ import { Settings, MemoryImportFormat } from './settingsSchema.js'; export type { Settings, MemoryImportFormat }; export const SETTINGS_DIRECTORY_NAME = '.gemini'; -export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME); -export const USER_SETTINGS_PATH = path.join(USER_SETTINGS_DIR, 'settings.json'); + +export const USER_SETTINGS_PATH = Storage.getGlobalSettingsPath(); +export const USER_SETTINGS_DIR = path.dirname(USER_SETTINGS_PATH); export const DEFAULT_EXCLUDED_ENV_VARS = ['DEBUG', 'DEBUG_MODE']; export function getSystemSettingsPath(): string { @@ -37,10 +39,6 @@ export function getSystemSettingsPath(): string { } } -export function getWorkspaceSettingsPath(workspaceDir: string): string { - return path.join(workspaceDir, SETTINGS_DIRECTORY_NAME, 'settings.json'); -} - export type { DnsResolutionOrder } from './settingsSchema.js'; export enum SettingScope { @@ -269,7 +267,9 @@ export function loadEnvironment(settings?: Settings): void { // If no settings provided, try to load workspace settings for exclusions let resolvedSettings = settings; if (!resolvedSettings) { - const workspaceSettingsPath = getWorkspaceSettingsPath(process.cwd()); + const workspaceSettingsPath = new Storage( + process.cwd(), + ).getWorkspaceSettingsPath(); try { if (fs.existsSync(workspaceSettingsPath)) { const workspaceContent = fs.readFileSync( @@ -342,7 +342,9 @@ export function loadSettings(workspaceDir: string): LoadedSettings { // We expect homedir to always exist and be resolvable. const realHomeDir = fs.realpathSync(resolvedHomeDir); - const workspaceSettingsPath = getWorkspaceSettingsPath(workspaceDir); + const workspaceSettingsPath = new Storage( + workspaceDir, + ).getWorkspaceSettingsPath(); // Load system settings try { |
