Skip to content

Commit 54003f8

Browse files
authored
debt - cleanup config migration (microsoft#152425)
1 parent b81bbef commit 54003f8

File tree

5 files changed

+99
-103
lines changed

5 files changed

+99
-103
lines changed

src/vs/workbench/browser/workbench.contribution.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ import { Registry } from 'vs/platform/registry/common/platform';
77
import { localize } from 'vs/nls';
88
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
99
import { isMacintosh, isWindows, isLinux, isWeb, isNative } from 'vs/base/common/platform';
10-
import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration';
10+
import { ConfigurationMigrationWorkbenchContribution, workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration';
1111
import { isStandalone } from 'vs/base/browser/browser';
12-
import 'vs/workbench/common/configurationMigration';
12+
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
13+
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
1314

1415
const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
1516

1617
// Configuration
1718
(function registerConfiguration(): void {
1819

20+
// Migration support
21+
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ConfigurationMigrationWorkbenchContribution, LifecyclePhase.Eventually);
22+
1923
// Workbench
2024
registry.registerConfiguration({
2125
...workbenchConfigurationNodeBase,

src/vs/workbench/common/configuration.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,101 @@
55

66
import { localize } from 'vs/nls';
77
import { IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
8+
import { Registry } from 'vs/platform/registry/common/platform';
9+
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
10+
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
11+
import { ConfigurationTarget, IConfigurationOverrides, IConfigurationService, IConfigurationValue } from 'vs/platform/configuration/common/configuration';
12+
import { Disposable } from 'vs/base/common/lifecycle';
13+
import { Emitter } from 'vs/base/common/event';
814

915
export const workbenchConfigurationNodeBase = Object.freeze<IConfigurationNode>({
1016
'id': 'workbench',
1117
'order': 7,
1218
'title': localize('workbenchConfigurationTitle', "Workbench"),
1319
'type': 'object',
1420
});
21+
22+
export const Extensions = {
23+
ConfigurationMigration: 'base.contributions.configuration.migration'
24+
};
25+
26+
export type ConfigurationValue = { value: any | undefined /* Remove */ };
27+
export type ConfigurationKeyValuePairs = [string, ConfigurationValue][];
28+
export type ConfigurationMigrationFn = (value: any, valueAccessor: (key: string) => any) => ConfigurationValue | ConfigurationKeyValuePairs | Promise<ConfigurationValue | ConfigurationKeyValuePairs>;
29+
export type ConfigurationMigration = { key: string; migrateFn: ConfigurationMigrationFn };
30+
31+
export interface IConfigurationMigrationRegistry {
32+
registerConfigurationMigrations(configurationMigrations: ConfigurationMigration[]): void;
33+
}
34+
35+
class ConfigurationMigrationRegistry implements IConfigurationMigrationRegistry {
36+
37+
readonly migrations: ConfigurationMigration[] = [];
38+
39+
private readonly _onDidRegisterConfigurationMigrations = new Emitter<ConfigurationMigration[]>();
40+
readonly onDidRegisterConfigurationMigration = this._onDidRegisterConfigurationMigrations.event;
41+
42+
registerConfigurationMigrations(configurationMigrations: ConfigurationMigration[]): void {
43+
this.migrations.push(...configurationMigrations);
44+
}
45+
46+
}
47+
48+
const configurationMigrationRegistry = new ConfigurationMigrationRegistry();
49+
Registry.add(Extensions.ConfigurationMigration, configurationMigrationRegistry);
50+
51+
export class ConfigurationMigrationWorkbenchContribution extends Disposable implements IWorkbenchContribution {
52+
53+
constructor(
54+
@IConfigurationService private readonly configurationService: IConfigurationService,
55+
@IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService,
56+
) {
57+
super();
58+
this._register(this.workspaceService.onDidChangeWorkspaceFolders(async (e) => {
59+
for (const folder of e.added) {
60+
await this.migrateConfigurationsForFolder(folder, configurationMigrationRegistry.migrations);
61+
}
62+
}));
63+
this.migrateConfigurations(configurationMigrationRegistry.migrations);
64+
this._register(configurationMigrationRegistry.onDidRegisterConfigurationMigration(migration => this.migrateConfigurations(migration)));
65+
}
66+
67+
private async migrateConfigurations(migrations: ConfigurationMigration[]): Promise<void> {
68+
await this.migrateConfigurationsForFolder(undefined, migrations);
69+
for (const folder of this.workspaceService.getWorkspace().folders) {
70+
await this.migrateConfigurationsForFolder(folder, migrations);
71+
}
72+
}
73+
74+
private async migrateConfigurationsForFolder(folder: IWorkspaceFolder | undefined, migrations: ConfigurationMigration[]): Promise<void> {
75+
await Promise.all(migrations.map(migration => this.migrateConfigurationsForFolderAndOverride(migration, { resource: folder?.uri })));
76+
}
77+
78+
private async migrateConfigurationsForFolderAndOverride(migration: ConfigurationMigration, overrides: IConfigurationOverrides): Promise<void> {
79+
const data = this.configurationService.inspect(migration.key, overrides);
80+
81+
await this.migrateConfigurationForFolderOverrideAndTarget(migration, overrides, data, 'userValue', ConfigurationTarget.USER);
82+
await this.migrateConfigurationForFolderOverrideAndTarget(migration, overrides, data, 'userLocalValue', ConfigurationTarget.USER_LOCAL);
83+
await this.migrateConfigurationForFolderOverrideAndTarget(migration, overrides, data, 'userRemoteValue', ConfigurationTarget.USER_REMOTE);
84+
await this.migrateConfigurationForFolderOverrideAndTarget(migration, overrides, data, 'workspaceFolderValue', ConfigurationTarget.WORKSPACE_FOLDER);
85+
await this.migrateConfigurationForFolderOverrideAndTarget(migration, overrides, data, 'workspaceValue', ConfigurationTarget.WORKSPACE);
86+
87+
if (typeof overrides.overrideIdentifier === 'undefined' && typeof data.overrideIdentifiers !== 'undefined') {
88+
for (const overrideIdentifier of data.overrideIdentifiers) {
89+
await this.migrateConfigurationsForFolderAndOverride(migration, { resource: overrides.resource, overrideIdentifier });
90+
}
91+
}
92+
}
93+
94+
private async migrateConfigurationForFolderOverrideAndTarget(migration: ConfigurationMigration, overrides: IConfigurationOverrides, data: IConfigurationValue<any>, dataKey: keyof IConfigurationValue<any>, target: ConfigurationTarget): Promise<void> {
95+
const value = data[dataKey];
96+
if (typeof value === 'undefined') {
97+
return;
98+
}
99+
100+
const valueAccessor = (key: string) => this.configurationService.inspect(key, overrides)[dataKey];
101+
const result = await migration.migrateFn(value, valueAccessor);
102+
const keyValuePairs: ConfigurationKeyValuePairs = Array.isArray(result) ? result : [[migration.key, result]];
103+
await Promise.allSettled(keyValuePairs.map(async ([key, value]) => this.configurationService.updateValue(key, value.value, overrides, target)));
104+
}
105+
}

src/vs/workbench/common/configurationMigration.ts

Lines changed: 0 additions & 99 deletions
This file was deleted.

src/vs/workbench/contrib/codeEditor/browser/editorSettingsMigration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { Registry } from 'vs/platform/registry/common/platform';
77
import { EditorSettingMigration, ISettingsWriter } from 'vs/editor/browser/config/migrateOptions';
8-
import { ConfigurationKeyValuePairs, Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configurationMigration';
8+
import { ConfigurationKeyValuePairs, Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configuration';
99

1010
Registry.as<IConfigurationMigrationRegistry>(Extensions.ConfigurationMigration)
1111
.registerConfigurationMigrations(EditorSettingMigration.items.map(item => ({

src/vs/workbench/contrib/search/browser/search.contribution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
5555
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
5656
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
5757
import { ISearchConfiguration, SearchSortOrder, SEARCH_EXCLUDE_CONFIG, VIEWLET_ID, VIEW_ID } from 'vs/workbench/services/search/common/search';
58-
import { Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configurationMigration';
58+
import { Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configuration';
5959

6060
registerSingleton(ISearchWorkbenchService, SearchWorkbenchService, true);
6161
registerSingleton(ISearchHistoryService, SearchHistoryService, true);

0 commit comments

Comments
 (0)