mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-21 01:07:46 +00:00
Ignore workspace settings for untrusted folders (#6606)
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { useState, useCallback, useEffect, useContext } from 'react';
|
||||
import { LoadedSettings, SettingScope } from '../../config/settings.js';
|
||||
import {
|
||||
AuthType,
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
getErrorMessage,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { runExitCleanup } from '../../utils/cleanup.js';
|
||||
import { SettingsContext } from '../contexts/SettingsContext.js';
|
||||
|
||||
export const useAuthCommand = (
|
||||
settings: LoadedSettings,
|
||||
@@ -22,6 +23,7 @@ export const useAuthCommand = (
|
||||
const [isAuthDialogOpen, setIsAuthDialogOpen] = useState(
|
||||
settings.merged.selectedAuthType === undefined,
|
||||
);
|
||||
const settingsContext = useContext(SettingsContext);
|
||||
|
||||
const openAuthDialog = useCallback(() => {
|
||||
setIsAuthDialogOpen(true);
|
||||
@@ -56,7 +58,7 @@ export const useAuthCommand = (
|
||||
if (authType) {
|
||||
await clearCachedCredentialFile();
|
||||
|
||||
settings.setValue(scope, 'selectedAuthType', authType);
|
||||
settingsContext?.settings.setValue(scope, 'selectedAuthType', authType);
|
||||
if (
|
||||
authType === AuthType.LOGIN_WITH_GOOGLE &&
|
||||
config.isBrowserLaunchSuppressed()
|
||||
@@ -75,7 +77,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
|
||||
setIsAuthDialogOpen(false);
|
||||
setAuthError(null);
|
||||
},
|
||||
[settings, setAuthError, config],
|
||||
[settingsContext, setAuthError, config],
|
||||
);
|
||||
|
||||
const cancelAuthentication = useCallback(() => {
|
||||
|
||||
@@ -23,6 +23,8 @@ import {
|
||||
checkHasEditorType,
|
||||
allowEditorTypeInSandbox,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { SettingsContext } from '../contexts/SettingsContext.js';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
vi.mock('@google/gemini-cli-core', async () => {
|
||||
const actual = await vi.importActual('@google/gemini-cli-core');
|
||||
@@ -43,13 +45,23 @@ describe('useEditorSettings', () => {
|
||||
(item: Omit<HistoryItem, 'id'>, timestamp: number) => void
|
||||
>;
|
||||
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<SettingsContext.Provider
|
||||
value={{ settings: mockLoadedSettings, recomputeSettings: () => {} }}
|
||||
>
|
||||
{children}
|
||||
</SettingsContext.Provider>
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
|
||||
mockLoadedSettings = {
|
||||
setValue: vi.fn(),
|
||||
} as unknown as LoadedSettings;
|
||||
|
||||
mockLoadedSettings = new LoadedSettings(
|
||||
{ path: '', settings: {} },
|
||||
{ path: '', settings: {} },
|
||||
{ path: '', settings: {} },
|
||||
[],
|
||||
);
|
||||
mockLoadedSettings.setValue = vi.fn();
|
||||
mockSetEditorError = vi.fn();
|
||||
mockAddItem = vi.fn();
|
||||
|
||||
@@ -63,16 +75,18 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should initialize with dialog closed', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
expect(result.current.isEditorDialogOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('should open editor dialog when openEditorDialog is called', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
act(() => {
|
||||
@@ -83,8 +97,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should close editor dialog when exitEditorDialog is called', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
act(() => {
|
||||
result.current.openEditorDialog();
|
||||
@@ -94,8 +109,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should handle editor selection successfully', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
const editorType: EditorType = 'vscode';
|
||||
@@ -125,8 +141,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should handle clearing editor preference (undefined editor)', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
const scope = SettingScope.Workspace;
|
||||
@@ -155,8 +172,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should handle different editor types', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
const editorTypes: EditorType[] = ['cursor', 'windsurf', 'vim'];
|
||||
@@ -184,8 +202,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should handle different setting scopes', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
const editorType: EditorType = 'vscode';
|
||||
@@ -213,8 +232,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should not set preference for unavailable editors', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
mockCheckHasEditorType.mockReturnValue(false);
|
||||
@@ -233,8 +253,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should not set preference for editors not allowed in sandbox', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
mockAllowEditorTypeInSandbox.mockReturnValue(false);
|
||||
@@ -253,8 +274,9 @@ describe('useEditorSettings', () => {
|
||||
});
|
||||
|
||||
it('should handle errors during editor selection', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEditorSettings(mockLoadedSettings, mockSetEditorError, mockAddItem),
|
||||
const { result } = renderHook(
|
||||
() => useEditorSettings(mockSetEditorError, mockAddItem),
|
||||
{ wrapper },
|
||||
);
|
||||
|
||||
const errorMessage = 'Failed to save settings';
|
||||
@@ -4,14 +4,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { LoadedSettings, SettingScope } from '../../config/settings.js';
|
||||
import { useState, useCallback, useContext } from 'react';
|
||||
import { SettingScope } from '../../config/settings.js';
|
||||
import { type HistoryItem, MessageType } from '../types.js';
|
||||
import {
|
||||
allowEditorTypeInSandbox,
|
||||
checkHasEditorType,
|
||||
EditorType,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { SettingsContext } from '../contexts/SettingsContext.js';
|
||||
|
||||
interface UseEditorSettingsReturn {
|
||||
isEditorDialogOpen: boolean;
|
||||
@@ -24,11 +25,11 @@ interface UseEditorSettingsReturn {
|
||||
}
|
||||
|
||||
export const useEditorSettings = (
|
||||
loadedSettings: LoadedSettings,
|
||||
setEditorError: (error: string | null) => void,
|
||||
addItem: (item: Omit<HistoryItem, 'id'>, timestamp: number) => void,
|
||||
): UseEditorSettingsReturn => {
|
||||
const [isEditorDialogOpen, setIsEditorDialogOpen] = useState(false);
|
||||
const settingsContext = useContext(SettingsContext);
|
||||
|
||||
const openEditorDialog = useCallback(() => {
|
||||
setIsEditorDialogOpen(true);
|
||||
@@ -45,7 +46,11 @@ export const useEditorSettings = (
|
||||
}
|
||||
|
||||
try {
|
||||
loadedSettings.setValue(scope, 'preferredEditor', editorType);
|
||||
settingsContext?.settings.setValue(
|
||||
scope,
|
||||
'preferredEditor',
|
||||
editorType,
|
||||
);
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
@@ -59,7 +64,7 @@ export const useEditorSettings = (
|
||||
setEditorError(`Failed to set editor preference: ${error}`);
|
||||
}
|
||||
},
|
||||
[loadedSettings, setEditorError, addItem],
|
||||
[settingsContext, setEditorError, addItem],
|
||||
);
|
||||
|
||||
const exitEditorDialog = useCallback(() => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { useState, useCallback, useEffect, useContext } from 'react';
|
||||
import { Settings, LoadedSettings } from '../../config/settings.js';
|
||||
import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
|
||||
import {
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
isWorkspaceTrusted,
|
||||
} from '../../config/trustedFolders.js';
|
||||
import * as process from 'process';
|
||||
import { SettingsContext } from '../contexts/SettingsContext.js';
|
||||
|
||||
export const useFolderTrust = (
|
||||
settings: LoadedSettings,
|
||||
@@ -20,6 +21,7 @@ export const useFolderTrust = (
|
||||
) => {
|
||||
const [isTrusted, setIsTrusted] = useState<boolean | undefined>(undefined);
|
||||
const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState(false);
|
||||
const settingsContext = useContext(SettingsContext);
|
||||
|
||||
const { folderTrust, folderTrustFeature } = settings.merged;
|
||||
useEffect(() => {
|
||||
@@ -60,8 +62,9 @@ export const useFolderTrust = (
|
||||
setIsTrusted(trusted);
|
||||
setIsFolderTrustDialogOpen(false);
|
||||
onTrustChange(trusted);
|
||||
settingsContext?.recomputeSettings();
|
||||
},
|
||||
[onTrustChange, folderTrust, folderTrustFeature],
|
||||
[onTrustChange, folderTrust, folderTrustFeature, settingsContext],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { useState, useCallback, useEffect, useContext } from 'react';
|
||||
import { themeManager } from '../themes/theme-manager.js';
|
||||
import { LoadedSettings, SettingScope } from '../../config/settings.js'; // Import LoadedSettings, AppSettings, MergedSetting
|
||||
import { type HistoryItem, MessageType } from '../types.js';
|
||||
import { HistoryItem, MessageType } from '../types.js';
|
||||
import { SettingScope } from '../../config/settings.js';
|
||||
import { SettingsContext } from '../contexts/SettingsContext.js';
|
||||
import process from 'node:process';
|
||||
|
||||
interface UseThemeCommandReturn {
|
||||
@@ -21,11 +22,12 @@ interface UseThemeCommandReturn {
|
||||
}
|
||||
|
||||
export const useThemeCommand = (
|
||||
loadedSettings: LoadedSettings,
|
||||
setThemeError: (error: string | null) => void,
|
||||
addItem: (item: Omit<HistoryItem, 'id'>, timestamp: number) => void,
|
||||
): UseThemeCommandReturn => {
|
||||
const [isThemeDialogOpen, setIsThemeDialogOpen] = useState(false);
|
||||
const settingsContext = useContext(SettingsContext);
|
||||
const loadedSettings = settingsContext!.settings;
|
||||
|
||||
// Check for invalid theme configuration on startup
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user