Fix setting migration nosiness and merging (#7571)
This commit is contained in:
parent
0c0309abdc
commit
52cc0f6feb
2 changed files with 85 additions and 17 deletions
|
|
@ -142,6 +142,11 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
tools: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
expect(settings.errors.length).toBe(0);
|
expect(settings.errors.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
@ -197,6 +202,13 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
tools: {
|
||||||
|
sandbox: false,
|
||||||
|
},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -253,6 +265,11 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
tools: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -308,6 +325,10 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -374,6 +395,10 @@ describe('Settings Loading and Merging', () => {
|
||||||
chatCompression: {},
|
chatCompression: {},
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -439,6 +464,7 @@ describe('Settings Loading and Merging', () => {
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
|
core: ['tool1'],
|
||||||
},
|
},
|
||||||
telemetry: { enabled: false },
|
telemetry: { enabled: false },
|
||||||
context: {
|
context: {
|
||||||
|
|
@ -460,6 +486,9 @@ describe('Settings Loading and Merging', () => {
|
||||||
chatCompression: {},
|
chatCompression: {},
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -538,6 +567,10 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
tools: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -668,7 +701,7 @@ describe('Settings Loading and Merging', () => {
|
||||||
chatCompression: {},
|
chatCompression: {},
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
telemetry: false,
|
telemetry: {},
|
||||||
tools: {
|
tools: {
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
},
|
},
|
||||||
|
|
@ -676,6 +709,9 @@ describe('Settings Loading and Merging', () => {
|
||||||
customThemes: {},
|
customThemes: {},
|
||||||
theme: 'system-theme',
|
theme: 'system-theme',
|
||||||
},
|
},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -901,7 +937,7 @@ describe('Settings Loading and Merging', () => {
|
||||||
(mockFsExistsSync as Mock).mockImplementation(
|
(mockFsExistsSync as Mock).mockImplementation(
|
||||||
(p: fs.PathLike) => p === USER_SETTINGS_PATH,
|
(p: fs.PathLike) => p === USER_SETTINGS_PATH,
|
||||||
);
|
);
|
||||||
const userSettingsContent = { telemetry: true };
|
const userSettingsContent = { telemetry: { enabled: true } };
|
||||||
(fs.readFileSync as Mock).mockImplementation(
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
(p: fs.PathOrFileDescriptor) => {
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
if (p === USER_SETTINGS_PATH)
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
|
@ -910,14 +946,14 @@ describe('Settings Loading and Merging', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
expect(settings.merged.telemetry).toBe(true);
|
expect(settings.merged.telemetry?.enabled).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load telemetry setting from workspace settings', () => {
|
it('should load telemetry setting from workspace settings', () => {
|
||||||
(mockFsExistsSync as Mock).mockImplementation(
|
(mockFsExistsSync as Mock).mockImplementation(
|
||||||
(p: fs.PathLike) => p === MOCK_WORKSPACE_SETTINGS_PATH,
|
(p: fs.PathLike) => p === MOCK_WORKSPACE_SETTINGS_PATH,
|
||||||
);
|
);
|
||||||
const workspaceSettingsContent = { telemetry: false };
|
const workspaceSettingsContent = { telemetry: { enabled: false } };
|
||||||
(fs.readFileSync as Mock).mockImplementation(
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
(p: fs.PathOrFileDescriptor) => {
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
|
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
|
||||||
|
|
@ -926,13 +962,13 @@ describe('Settings Loading and Merging', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
expect(settings.merged.telemetry).toBe(false);
|
expect(settings.merged.telemetry?.enabled).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should prioritize workspace telemetry setting over user setting', () => {
|
it('should prioritize workspace telemetry setting over user setting', () => {
|
||||||
(mockFsExistsSync as Mock).mockReturnValue(true);
|
(mockFsExistsSync as Mock).mockReturnValue(true);
|
||||||
const userSettingsContent = { telemetry: true };
|
const userSettingsContent = { telemetry: { enabled: true } };
|
||||||
const workspaceSettingsContent = { telemetry: false };
|
const workspaceSettingsContent = { telemetry: { enabled: false } };
|
||||||
(fs.readFileSync as Mock).mockImplementation(
|
(fs.readFileSync as Mock).mockImplementation(
|
||||||
(p: fs.PathOrFileDescriptor) => {
|
(p: fs.PathOrFileDescriptor) => {
|
||||||
if (p === USER_SETTINGS_PATH)
|
if (p === USER_SETTINGS_PATH)
|
||||||
|
|
@ -943,14 +979,14 @@ describe('Settings Loading and Merging', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
expect(settings.merged.telemetry).toBe(false);
|
expect(settings.merged.telemetry?.enabled).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have telemetry as undefined if not in any settings file', () => {
|
it('should have telemetry as undefined if not in any settings file', () => {
|
||||||
(mockFsExistsSync as Mock).mockReturnValue(false); // No settings files exist
|
(mockFsExistsSync as Mock).mockReturnValue(false); // No settings files exist
|
||||||
(fs.readFileSync as Mock).mockReturnValue('{}');
|
(fs.readFileSync as Mock).mockReturnValue('{}');
|
||||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||||
expect(settings.merged.telemetry).toBeUndefined();
|
expect(settings.merged.telemetry).toEqual({});
|
||||||
expect(settings.merged.ui?.customThemes).toEqual({});
|
expect(settings.merged.ui?.customThemes).toEqual({});
|
||||||
expect(settings.merged.mcpServers).toEqual({});
|
expect(settings.merged.mcpServers).toEqual({});
|
||||||
});
|
});
|
||||||
|
|
@ -1400,6 +1436,11 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
tools: {},
|
||||||
|
telemetry: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check that error objects are populated in settings.errors
|
// Check that error objects are populated in settings.errors
|
||||||
|
|
@ -1828,6 +1869,10 @@ describe('Settings Loading and Merging', () => {
|
||||||
workspacesWithMigrationNudge: [],
|
workspacesWithMigrationNudge: [],
|
||||||
},
|
},
|
||||||
security: {},
|
security: {},
|
||||||
|
general: {},
|
||||||
|
privacy: {},
|
||||||
|
telemetry: {},
|
||||||
|
ide: {},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ export const DEFAULT_EXCLUDED_ENV_VARS = ['DEBUG', 'DEBUG_MODE'];
|
||||||
|
|
||||||
const MIGRATE_V2_OVERWRITE = false;
|
const MIGRATE_V2_OVERWRITE = false;
|
||||||
|
|
||||||
// As defined in spec.md
|
|
||||||
const MIGRATION_MAP: Record<string, string> = {
|
const MIGRATION_MAP: Record<string, string> = {
|
||||||
preferredEditor: 'general.preferredEditor',
|
preferredEditor: 'general.preferredEditor',
|
||||||
vimMode: 'general.vimMode',
|
vimMode: 'general.vimMode',
|
||||||
|
|
@ -63,6 +62,7 @@ const MIGRATION_MAP: Record<string, string> = {
|
||||||
fileFiltering: 'context.fileFiltering',
|
fileFiltering: 'context.fileFiltering',
|
||||||
sandbox: 'tools.sandbox',
|
sandbox: 'tools.sandbox',
|
||||||
shouldUseNodePtyShell: 'tools.usePty',
|
shouldUseNodePtyShell: 'tools.usePty',
|
||||||
|
allowedTools: 'tools.allowed',
|
||||||
coreTools: 'tools.core',
|
coreTools: 'tools.core',
|
||||||
excludeTools: 'tools.exclude',
|
excludeTools: 'tools.exclude',
|
||||||
toolDiscoveryCommand: 'tools.discoveryCommand',
|
toolDiscoveryCommand: 'tools.discoveryCommand',
|
||||||
|
|
@ -299,6 +299,12 @@ function mergeSettings(
|
||||||
...user,
|
...user,
|
||||||
...safeWorkspaceWithoutFolderTrust,
|
...safeWorkspaceWithoutFolderTrust,
|
||||||
...system,
|
...system,
|
||||||
|
general: {
|
||||||
|
...(systemDefaults.general || {}),
|
||||||
|
...(user.general || {}),
|
||||||
|
...(safeWorkspaceWithoutFolderTrust.general || {}),
|
||||||
|
...(system.general || {}),
|
||||||
|
},
|
||||||
ui: {
|
ui: {
|
||||||
...(systemDefaults.ui || {}),
|
...(systemDefaults.ui || {}),
|
||||||
...(user.ui || {}),
|
...(user.ui || {}),
|
||||||
|
|
@ -311,6 +317,24 @@ function mergeSettings(
|
||||||
...(system.ui?.customThemes || {}),
|
...(system.ui?.customThemes || {}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ide: {
|
||||||
|
...(systemDefaults.ide || {}),
|
||||||
|
...(user.ide || {}),
|
||||||
|
...(safeWorkspaceWithoutFolderTrust.ide || {}),
|
||||||
|
...(system.ide || {}),
|
||||||
|
},
|
||||||
|
privacy: {
|
||||||
|
...(systemDefaults.privacy || {}),
|
||||||
|
...(user.privacy || {}),
|
||||||
|
...(safeWorkspaceWithoutFolderTrust.privacy || {}),
|
||||||
|
...(system.privacy || {}),
|
||||||
|
},
|
||||||
|
telemetry: {
|
||||||
|
...(systemDefaults.telemetry || {}),
|
||||||
|
...(user.telemetry || {}),
|
||||||
|
...(safeWorkspaceWithoutFolderTrust.telemetry || {}),
|
||||||
|
...(system.telemetry || {}),
|
||||||
|
},
|
||||||
security: {
|
security: {
|
||||||
...(systemDefaults.security || {}),
|
...(systemDefaults.security || {}),
|
||||||
...(user.security || {}),
|
...(user.security || {}),
|
||||||
|
|
@ -329,6 +353,12 @@ function mergeSettings(
|
||||||
...(safeWorkspaceWithoutFolderTrust.mcpServers || {}),
|
...(safeWorkspaceWithoutFolderTrust.mcpServers || {}),
|
||||||
...(system.mcpServers || {}),
|
...(system.mcpServers || {}),
|
||||||
},
|
},
|
||||||
|
tools: {
|
||||||
|
...(systemDefaults.tools || {}),
|
||||||
|
...(user.tools || {}),
|
||||||
|
...(safeWorkspaceWithoutFolderTrust.tools || {}),
|
||||||
|
...(system.tools || {}),
|
||||||
|
},
|
||||||
context: {
|
context: {
|
||||||
...(systemDefaults.context || {}),
|
...(systemDefaults.context || {}),
|
||||||
...(user.context || {}),
|
...(user.context || {}),
|
||||||
|
|
@ -667,7 +697,6 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
|
||||||
|
|
||||||
let settingsObject = rawSettings as Record<string, unknown>;
|
let settingsObject = rawSettings as Record<string, unknown>;
|
||||||
if (needsMigration(settingsObject)) {
|
if (needsMigration(settingsObject)) {
|
||||||
console.error(`Legacy settings file detected at: ${filePath}`);
|
|
||||||
const migratedSettings = migrateSettingsToV2(settingsObject);
|
const migratedSettings = migrateSettingsToV2(settingsObject);
|
||||||
if (migratedSettings) {
|
if (migratedSettings) {
|
||||||
if (MIGRATE_V2_OVERWRITE) {
|
if (MIGRATE_V2_OVERWRITE) {
|
||||||
|
|
@ -678,9 +707,6 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
|
||||||
JSON.stringify(migratedSettings, null, 2),
|
JSON.stringify(migratedSettings, null, 2),
|
||||||
'utf-8',
|
'utf-8',
|
||||||
);
|
);
|
||||||
console.log(
|
|
||||||
`Successfully migrated and saved settings file: ${filePath}`,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
`Error migrating settings file on disk: ${getErrorMessage(
|
`Error migrating settings file on disk: ${getErrorMessage(
|
||||||
|
|
@ -689,9 +715,6 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
|
||||||
`Successfully migrated settings for ${filePath} in-memory for the current session.`,
|
|
||||||
);
|
|
||||||
migratedInMemorScopes.add(scope);
|
migratedInMemorScopes.add(scope);
|
||||||
}
|
}
|
||||||
settingsObject = migratedSettings;
|
settingsObject = migratedSettings;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue