fix: Restart logic in useFolderTrust hook (#8038)

This commit is contained in:
shrutip90
2025-09-08 14:43:49 -07:00
committed by GitHub
parent c8dfab9ec6
commit 097b5c734f
3 changed files with 32 additions and 26 deletions

View File

@@ -668,7 +668,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } =
useFolderTrust(settings, config, setIsTrustedFolder, refreshStatic);
useFolderTrust(settings, setIsTrustedFolder, refreshStatic);
const { needsRestart: ideNeedsRestart } = useIdeTrustListener();
const isInitialMount = useRef(true);

View File

@@ -22,7 +22,6 @@ vi.mock('process', () => ({
describe('useFolderTrust', () => {
let mockSettings: LoadedSettings;
let mockConfig: unknown;
let mockTrustedFolders: LoadedTrustedFolders;
let loadTrustedFoldersSpy: vi.SpyInstance;
let isWorkspaceTrustedSpy: vi.SpyInstance;
@@ -41,8 +40,6 @@ describe('useFolderTrust', () => {
setValue: vi.fn(),
} as unknown as LoadedSettings;
mockConfig = {} as unknown;
mockTrustedFolders = {
setValue: vi.fn(),
} as unknown as LoadedTrustedFolders;
@@ -63,7 +60,7 @@ describe('useFolderTrust', () => {
it('should not open dialog when folder is already trusted', () => {
isWorkspaceTrustedSpy.mockReturnValue(true);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
expect(result.current.isFolderTrustDialogOpen).toBe(false);
expect(onTrustChange).toHaveBeenCalledWith(true);
@@ -72,7 +69,7 @@ describe('useFolderTrust', () => {
it('should not open dialog when folder is already untrusted', () => {
isWorkspaceTrustedSpy.mockReturnValue(false);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
expect(result.current.isFolderTrustDialogOpen).toBe(false);
expect(onTrustChange).toHaveBeenCalledWith(false);
@@ -81,7 +78,7 @@ describe('useFolderTrust', () => {
it('should open dialog when folder trust is undefined', () => {
isWorkspaceTrustedSpy.mockReturnValue(undefined);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
expect(result.current.isFolderTrustDialogOpen).toBe(true);
expect(onTrustChange).toHaveBeenCalledWith(undefined);
@@ -92,7 +89,7 @@ describe('useFolderTrust', () => {
.mockReturnValueOnce(undefined)
.mockReturnValueOnce(true);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
isWorkspaceTrustedSpy.mockReturnValue(true);
@@ -114,7 +111,7 @@ describe('useFolderTrust', () => {
.mockReturnValueOnce(undefined)
.mockReturnValueOnce(true);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
act(() => {
@@ -134,7 +131,7 @@ describe('useFolderTrust', () => {
.mockReturnValueOnce(undefined)
.mockReturnValueOnce(false);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
act(() => {
@@ -146,14 +143,14 @@ describe('useFolderTrust', () => {
TrustLevel.DO_NOT_TRUST,
);
expect(onTrustChange).toHaveBeenLastCalledWith(false);
expect(result.current.isRestarting).toBe(false);
expect(result.current.isFolderTrustDialogOpen).toBe(false);
expect(result.current.isRestarting).toBe(true);
expect(result.current.isFolderTrustDialogOpen).toBe(true);
});
it('should do nothing for default choice', () => {
isWorkspaceTrustedSpy.mockReturnValue(undefined);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
act(() => {
@@ -171,15 +168,15 @@ describe('useFolderTrust', () => {
it('should set isRestarting to true when trust status changes from false to true', () => {
isWorkspaceTrustedSpy.mockReturnValueOnce(false).mockReturnValueOnce(true); // Initially untrusted, then trusted
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
act(() => {
result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_FOLDER);
});
expect(result.current.isRestarting).toBe(false);
expect(result.current.isFolderTrustDialogOpen).toBe(false); // Dialog should close after selection
expect(result.current.isRestarting).toBe(true);
expect(result.current.isFolderTrustDialogOpen).toBe(true); // Dialog should stay open
});
it('should not set isRestarting to true when trust status does not change', () => {
@@ -187,7 +184,7 @@ describe('useFolderTrust', () => {
.mockReturnValueOnce(undefined)
.mockReturnValueOnce(true); // Initially undefined, then trust
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
act(() => {
@@ -201,7 +198,7 @@ describe('useFolderTrust', () => {
it('should call refreshStatic when dialog opens and closes', () => {
isWorkspaceTrustedSpy.mockReturnValue(undefined);
const { result } = renderHook(() =>
useFolderTrust(mockSettings, mockConfig, onTrustChange, refreshStatic),
useFolderTrust(mockSettings, onTrustChange, refreshStatic),
);
// The hook runs, isFolderTrustDialogOpen becomes true, useEffect triggers.

View File

@@ -5,7 +5,6 @@
*/
import { useState, useCallback, useEffect } from 'react';
import { type Config } from '@google/gemini-cli-core';
import type { LoadedSettings } from '../../config/settings.js';
import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
import {
@@ -17,13 +16,12 @@ import * as process from 'node:process';
export const useFolderTrust = (
settings: LoadedSettings,
config: Config,
onTrustChange: (isTrusted: boolean | undefined) => void,
refreshStatic: () => void,
) => {
const [isTrusted, setIsTrusted] = useState<boolean | undefined>(undefined);
const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState(false);
const [isRestarting] = useState(false);
const [isRestarting, setIsRestarting] = useState(false);
const folderTrust = settings.merged.security?.folderTrust?.enabled;
@@ -46,6 +44,8 @@ export const useFolderTrust = (
const cwd = process.cwd();
let trustLevel: TrustLevel;
const wasTrusted = isTrusted ?? true;
switch (choice) {
case FolderTrustChoice.TRUST_FOLDER:
trustLevel = TrustLevel.TRUST_FOLDER;
@@ -61,12 +61,21 @@ export const useFolderTrust = (
}
trustedFolders.setValue(cwd, trustLevel);
const trusted = isWorkspaceTrusted(settings.merged);
setIsTrusted(trusted);
setIsFolderTrustDialogOpen(false);
onTrustChange(trusted);
const currentIsTrusted =
trustLevel === TrustLevel.TRUST_FOLDER ||
trustLevel === TrustLevel.TRUST_PARENT;
setIsTrusted(currentIsTrusted);
onTrustChange(currentIsTrusted);
const needsRestart = wasTrusted !== currentIsTrusted;
if (needsRestart) {
setIsRestarting(true);
setIsFolderTrustDialogOpen(true);
} else {
setIsFolderTrustDialogOpen(false);
}
},
[settings.merged, onTrustChange],
[onTrustChange, isTrusted],
);
return {