Skip to content

Commit

Permalink
feat: add a way to initialize configuration and keybindings before th…
Browse files Browse the repository at this point in the history
…e services are initialized
  • Loading branch information
Loïc Mangeonjean committed Nov 9, 2023
1 parent 8ab0090 commit 9979c97
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
22 changes: 19 additions & 3 deletions src/service-override/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ConfigurationScope } from 'vscode/src/vs/platform/configuration/common/
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationNode, IConfigurationDefaults } from 'vs/platform/configuration/common/configurationRegistry'
import { Registry } from 'vs/platform/registry/common/platform'
import { VSBuffer } from 'vs/base/common/buffer'
import { IFileService } from 'vs/platform/files/common/files'
import { IFileService, IFileWriteOptions } from 'vs/platform/files/common/files'
import { ILogService } from 'vs/platform/log/common/log'
import { IColorCustomizations, IThemeScopedColorCustomizations } from 'vs/workbench/services/themes/common/workbenchThemeService'
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'
Expand All @@ -32,12 +32,26 @@ import { AbstractWorkspaceEditingService } from 'vs/workbench/services/workspace
import { URI } from 'vs/base/common/uri'
import 'vs/workbench/api/common/configurationExtensionPoint'
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'
import getFileServiceOverride from './files'
import getFileServiceOverride, { initFile } from './files'
import { memoizedConstructor, unsupported } from '../tools'
import { registerServiceInitializePreParticipant } from '../lifecycle'
import { getService } from '../services'

// This is the default value, but can be overriden by overriding the Environment or UserDataProfileService service
const defaultUserConfigurationFile = URI.from({ scheme: Schemas.vscodeUserData, path: '/User/settings.json' })

/**
* Should be called only BEFORE the service are initialized to initialize the file on the filesystem before the configuration service initializes
*/
async function initUserConfiguration (configurationJson: string, options?: Partial<IFileWriteOptions>, file: URI = defaultUserConfigurationFile): Promise<void> {
await initFile(defaultUserConfigurationFile.scheme, file, configurationJson, options)
}

/**
* Can be called at any time after the services are initialized to update the user configuration
*/
async function updateUserConfiguration (configurationJson: string): Promise<void> {
const userDataProfilesService = StandaloneServices.get(IUserDataProfilesService)
const userDataProfilesService = await getService(IUserDataProfilesService)
await StandaloneServices.get(IFileService).writeFile(userDataProfilesService.defaultProfile.settingsResource, VSBuffer.fromString(configurationJson))
}

Expand Down Expand Up @@ -125,6 +139,8 @@ export default function getServiceOverride (defaultWorkspace: URI | IAnyWorkspac
}

export {
defaultUserConfigurationFile,
initUserConfiguration,
updateUserConfiguration,
getUserConfiguration,
onUserConfigurationChange,
Expand Down
25 changes: 24 additions & 1 deletion src/service-override/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,11 +460,16 @@ const fileSystemProvider = new OverlayFileSystemProvider()
fileSystemProvider.register(0, new MkdirpOnWriteInMemoryFileSystemProvider())

const extensionFileSystemProvider = new RegisteredFileSystemProvider(true)
const userDataFileSystemProvider = new InMemoryFileSystemProvider()

// Initialize /User/ folder to be able to write configuration and keybindings in it before the fileService is initialized
// The `mkdirp` logic is inside the service, and the provider will just fail if asked to write a file in a non-existent directory
void userDataFileSystemProvider.mkdir(URI.from({ scheme: Schemas.vscodeUserData, path: '/User/' }))

const providers: Record<string, IFileSystemProvider> = {
extension: extensionFileSystemProvider,
logs: new InMemoryFileSystemProvider(),
[Schemas.vscodeUserData]: new InMemoryFileSystemProvider(),
[Schemas.vscodeUserData]: userDataFileSystemProvider,
[Schemas.tmp]: new InMemoryFileSystemProvider(),
file: fileSystemProvider
}
Expand Down Expand Up @@ -503,6 +508,24 @@ export function registerExtensionFile (extensionLocation: URI, filePath: string,
return extensionFileSystemProvider.registerFile(new RegisteredReadOnlyFile(joinPath(extensionLocation, filePath), getContent))
}

/**
* Can be used to create a file before the fileService is initialized
*/
export async function initFile (scheme: string, file: URI, content: Uint8Array | string, options?: Partial<IFileWriteOptions>): Promise<void> {
const provider = providers[scheme]
if (provider == null || provider.writeFile == null) {
throw new Error(`${scheme} provider doesn't exist or doesn't support writing files`)
}

await provider.writeFile(file, content instanceof Uint8Array ? content : encoder.encode(content), {
atomic: false,
create: true,
overwrite: false,
unlock: false,
...options
})
}

/**
* Register a file system overlay
*
Expand Down
26 changes: 22 additions & 4 deletions src/service-override/keybindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { VSBuffer } from 'vs/base/common/buffer'
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'
import { IKeyboardLayoutService } from 'vs/platform/keyboardLayout/common/keyboardLayout'
import { BrowserKeyboardLayoutService } from 'vs/workbench/services/keybinding/browser/keyboardLayoutService'
import { IFileService } from 'vs/platform/files/common/files'
import { IFileService, IFileWriteOptions } from 'vs/platform/files/common/files'
import { ICommandService } from 'vs/platform/commands/common/commands'
import { CommandService } from 'vs/workbench/services/commands/common/commandService'
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'
Expand All @@ -21,12 +21,28 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'
import { ILogService } from 'vs/platform/log/common/log'
import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'
import getFileServiceOverride from './files'
import { Schemas } from 'vs/base/common/network'
import { URI } from 'vs/base/common/uri'
import getFileServiceOverride, { initFile } from './files'
import { DynamicKeybindingService } from '../monaco'
import 'vs/workbench/browser/workbench.contribution'
import 'vs/workbench/contrib/keybindings/browser/keybindings.contribution'
import { onRenderWorkbench } from '../lifecycle'
import { IInstantiationService } from '../services'
import 'vs/workbench/browser/workbench.contribution'
import 'vs/workbench/contrib/keybindings/browser/keybindings.contribution'

// This is the default value, but can be overriden by overriding the Environment or UserDataProfileService service
const defaultUserKeybindindsFile = URI.from({ scheme: Schemas.vscodeUserData, path: '/User/keybindings.json' })

/**
* Should be called only BEFORE the service are initialized to initialize the file on the filesystem before the keybindings service initializes
*/
async function initUserKeybindings (configurationJson: string, options?: Partial<IFileWriteOptions>, file: URI = defaultUserKeybindindsFile): Promise<void> {
await initFile(defaultUserKeybindindsFile.scheme, file, configurationJson, options)
}

/**
* Can be called at any time after the services are initialized to update the user configuration
*/

async function updateUserKeybindings (keybindingsJson: string): Promise<void> {
const userDataProfilesService: IUserDataProfilesService = StandaloneServices.get(IUserDataProfilesService)
Expand Down Expand Up @@ -100,6 +116,8 @@ export default function getServiceOverride ({ shouldUseGlobalKeybindings = () =>
}

export {
defaultUserKeybindindsFile,
initUserKeybindings,
updateUserKeybindings,
IUserFriendlyKeybinding
}

0 comments on commit 9979c97

Please sign in to comment.