diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 97578e19252..e71b758a7f7 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -161,7 +161,7 @@ class CodeMain { environmentService.logsPath, environmentService.globalStorageHome, environmentService.workspaceStorageHome, - environmentService.backupHome + environmentService.backupHome.fsPath ].map((path): undefined | Promise => path ? mkdirp(path) : undefined)); // Configuration service diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 377ca33281c..ad3025e5c3c 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -1331,7 +1331,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService { // For all other cases we first call into registerEmptyWindowBackupSync() to set it before // loading the window. if (options.emptyWindowBackupInfo) { - configuration.backupPath = join(this.environmentService.backupHome, options.emptyWindowBackupInfo.backupFolder); + configuration.backupPath = join(this.environmentService.backupHome.fsPath, options.emptyWindowBackupInfo.backupFolder); } let window: ICodeWindow | undefined; diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index 011164d869e..9e2875d928a 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -36,7 +36,7 @@ export class BackupMainService implements IBackupMainService { @IConfigurationService private readonly configurationService: IConfigurationService, @ILogService private readonly logService: ILogService ) { - this.backupHome = environmentService.backupHome; + this.backupHome = environmentService.backupHome.fsPath; this.workspacesJsonPath = environmentService.backupWorkspacesPath; } diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index 422ec4493a6..189d930f7b7 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -124,7 +124,7 @@ export interface IEnvironmentService { globalStorageHome: string; workspaceStorageHome: string; - backupHome: string; + backupHome: URI; backupWorkspacesPath: string; untitledWorkspacesHome: URI; diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 744c9b936fe..0b2fd7547db 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -151,10 +151,10 @@ export class EnvironmentService implements IEnvironmentService { get isExtensionDevelopment(): boolean { return !!this._args.extensionDevelopmentPath; } @memoize - get backupHome(): string { return path.join(this.userDataPath, BACKUPS); } + get backupHome(): URI { return URI.file(path.join(this.userDataPath, BACKUPS)); } @memoize - get backupWorkspacesPath(): string { return path.join(this.backupHome, 'workspaces.json'); } + get backupWorkspacesPath(): string { return path.join(this.backupHome.fsPath, 'workspaces.json'); } @memoize get untitledWorkspacesHome(): URI { return URI.file(path.join(this.userDataPath, 'Workspaces')); } diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index dadc532e49f..f653479fb9b 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -84,8 +84,7 @@ class CodeRendererMain extends Disposable { serviceCollection.set(ILogService, logService); // Environment - const remoteUserDataUri = this.getRemoteUserDataUri(); - const environmentService = new BrowserWorkbenchEnvironmentService(this.configuration, remoteUserDataUri); + const environmentService = new BrowserWorkbenchEnvironmentService(this.configuration); serviceCollection.set(IWorkbenchEnvironmentService, environmentService); // Product @@ -116,8 +115,11 @@ class CodeRendererMain extends Disposable { fileService.registerProvider(Schemas.vscodeRemote, remoteFileSystemProvider); - if (!userDataProvider && remoteUserDataUri) { - userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, dirname(remoteUserDataUri), remoteFileSystemProvider)); + if (!userDataProvider) { + const remoteUserDataUri = this.getRemoteUserDataUri(); + if (remoteUserDataUri) { + userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, dirname(remoteUserDataUri), remoteFileSystemProvider, environmentService)); + } } } diff --git a/src/vs/workbench/electron-browser/main.ts b/src/vs/workbench/electron-browser/main.ts index c7542c63abe..7ba3089f538 100644 --- a/src/vs/workbench/electron-browser/main.ts +++ b/src/vs/workbench/electron-browser/main.ts @@ -200,7 +200,7 @@ class CodeRendererMain extends Disposable { fileService.registerProvider(Schemas.file, diskFileSystemProvider); // User Data Provider - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, URI.file(environmentService.backupHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const connection = remoteAgentService.getConnection(); if (connection) { diff --git a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts b/src/vs/workbench/services/backup/test/node/backupFileService.test.ts index 3b44c4f67b2..2407186c794 100644 --- a/src/vs/workbench/services/backup/test/node/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/node/backupFileService.test.ts @@ -62,7 +62,7 @@ class TestBackupFileService extends BackupFileService { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, URI.file(environmentService.backupHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); super(environmentService, fileService); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index be0cfec3420..1b604be8ba7 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -42,9 +42,8 @@ import { KeybindingsEditingService, IKeybindingEditingService } from 'vs/workben import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/node/environmentService'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider'; -import { dirname } from 'vs/base/common/resources'; -class TestBackupEnvironmentService extends WorkbenchEnvironmentService { +class TestEnvironmentService extends WorkbenchEnvironmentService { constructor(private _appSettingsHome: URI) { super(parseArgs(process.argv) as IWindowConfiguration, process.execPath); @@ -105,13 +104,13 @@ suite('ConfigurationEditingService', () => { clearServices(); instantiationService = workbenchInstantiationService(); - const environmentService = new TestBackupEnvironmentService(URI.file(workspaceDir)); + const environmentService = new TestEnvironmentService(URI.file(workspaceDir)); instantiationService.stub(IEnvironmentService, environmentService); const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(URI.file(workspaceDir), dirname(URI.file(workspaceDir)), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); instantiationService.stub(IFileService, fileService); instantiationService.stub(IRemoteAgentService, remoteAgentService); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 308b976db11..a477c2a1f4f 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -30,7 +30,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService'; import { createHash } from 'crypto'; import { Schemas } from 'vs/base/common/network'; -import { originalFSPath, dirname } from 'vs/base/common/resources'; +import { originalFSPath } from 'vs/base/common/resources'; import { isLinux } from 'vs/base/common/platform'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; @@ -107,7 +107,7 @@ suite('WorkspaceContextService - Folder', () => { workspaceResource = folderDir; const environmentService = new TestEnvironmentService(URI.file(parentDir)); const fileService = new FileService(new NullLogService()); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), new DiskFileSystemProvider(new NullLogService()))); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, new DiskFileSystemProvider(new NullLogService()), environmentService)); workspaceContextService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, new RemoteAgentService({}, environmentService, new RemoteAuthorityResolverService(), new SignService())); return (workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir))); }); @@ -173,7 +173,7 @@ suite('WorkspaceContextService - Workspace', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); @@ -233,7 +233,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); @@ -494,7 +494,7 @@ suite('WorkspaceService - Initialization', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -758,7 +758,7 @@ suite('WorkspaceConfigurationService - Folder', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -1088,7 +1088,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); @@ -1490,7 +1490,7 @@ suite('WorkspaceConfigurationService - Remote Folder', () => { const remoteAgentService = instantiationService.stub(IRemoteAgentService, >{ getEnvironment: () => remoteEnvironmentPromise }); const fileService = new FileService(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); const configurationCache: IConfigurationCache = { read: () => Promise.resolve(''), write: () => Promise.resolve(), remove: () => Promise.resolve() }; testObject = new WorkspaceService({ configurationCache, remoteAuthority }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, testObject); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index e1e86e4a937..74cb8d155d8 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -63,13 +63,13 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { readonly configuration: IWindowConfiguration = new BrowserWindowConfiguration(); - constructor(configuration: IWorkbenchConstructionOptions, remoteUserDataUri: URI | null) { + constructor(configuration: IWorkbenchConstructionOptions) { this.args = { _: [] }; this.appRoot = '/web/'; this.appNameLong = 'Visual Studio Code - Web'; this.configuration.remoteAuthority = configuration.remoteAuthority; - this.userRoamingDataHome = remoteUserDataUri ? remoteUserDataUri.with({ scheme: Schemas.userData }) : URI.file('/User').with({ scheme: Schemas.userData }); + this.userRoamingDataHome = URI.file('/User').with({ scheme: Schemas.userData }); this.settingsResource = joinPath(this.userRoamingDataHome, 'settings.json'); this.keybindingsResource = joinPath(this.userRoamingDataHome, 'keybindings.json'); this.keyboardLayoutResource = joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); @@ -108,7 +108,7 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { settingsSearchUrl?: string; globalStorageHome: string; workspaceStorageHome: string; - backupHome: string; + backupHome: URI; backupWorkspacesPath: string; workspacesHome: string; isExtensionDevelopment: boolean; diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index dc8b05ca6f8..c6599181ee5 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -49,9 +49,8 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file import { parseArgs } from 'vs/platform/environment/node/argv'; import { WorkbenchEnvironmentService } from 'vs/workbench/services/environment/node/environmentService'; import { IWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { dirname } from 'vs/base/common/resources'; -class TestBackupEnvironmentService extends WorkbenchEnvironmentService { +class TestEnvironmentService extends WorkbenchEnvironmentService { constructor(private _appSettingsHome: URI) { super(parseArgs(process.argv) as IWindowConfiguration, process.execPath); @@ -81,7 +80,7 @@ suite('KeybindingsEditing', () => { instantiationService = new TestInstantiationService(); - const environmentService = new TestBackupEnvironmentService(URI.file(testDir)); + const environmentService = new TestEnvironmentService(URI.file(testDir)); instantiationService.stub(IEnvironmentService, environmentService); instantiationService.stub(IConfigurationService, ConfigurationService); instantiationService.stub(IConfigurationService, 'getValue', { 'eol': '\n' }); @@ -101,7 +100,7 @@ suite('KeybindingsEditing', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, dirname(environmentService.appSettingsHome), diskFileSystemProvider)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); instantiationService.stub(IFileService, fileService); instantiationService.stub(IUntitledEditorService, instantiationService.createInstance(UntitledEditorService)); instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); diff --git a/src/vs/workbench/services/userData/common/fileUserDataProvider.ts b/src/vs/workbench/services/userData/common/fileUserDataProvider.ts index d4dd8d7abb7..008fc7d2b98 100644 --- a/src/vs/workbench/services/userData/common/fileUserDataProvider.ts +++ b/src/vs/workbench/services/userData/common/fileUserDataProvider.ts @@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri'; import * as resources from 'vs/base/common/resources'; import { startsWith } from 'vs/base/common/strings'; import { BACKUPS } from 'vs/platform/environment/common/environment'; -import { Schemas } from 'vs/base/common/network'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; export class FileUserDataProvider extends Disposable implements IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithOpenReadWriteCloseCapability { @@ -20,15 +20,20 @@ export class FileUserDataProvider extends Disposable implements IFileSystemProvi private readonly _onDidChangeFile: Emitter = this._register(new Emitter()); readonly onDidChangeFile: Event = this._onDidChangeFile.event; + private readonly userDataHome: URI; + constructor( - private readonly userDataHome: URI, - private readonly backupsHome: URI, + private readonly fileSystemUserDataHome: URI, + private readonly fileSystemBackupsHome: URI, private readonly fileSystemProvider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability, + environmentService: IWorkbenchEnvironmentService ) { super(); + this.userDataHome = environmentService.userRoamingDataHome; + // Assumption: This path always exists - this._register(this.fileSystemProvider.watch(this.userDataHome, { recursive: false, excludes: [] })); + this._register(this.fileSystemProvider.watch(this.fileSystemUserDataHome, { recursive: false, excludes: [] })); this._register(this.fileSystemProvider.onDidChangeFile(e => this.handleFileChanges(e))); } @@ -115,21 +120,21 @@ export class FileUserDataProvider extends Disposable implements IFileSystemProvi } private toFileSystemResource(userDataResource: URI): URI { - const fileSystemResource = userDataResource.with({ scheme: this.userDataHome.scheme }); - const relativePath = resources.relativePath(this.userDataHome, fileSystemResource); - if (relativePath && startsWith(relativePath, BACKUPS)) { - return resources.joinPath(resources.dirname(this.backupsHome), relativePath); + const relativePath = resources.relativePath(this.userDataHome, userDataResource)!; + if (startsWith(relativePath, BACKUPS)) { + return resources.joinPath(resources.dirname(this.fileSystemBackupsHome), relativePath); } - return fileSystemResource; + return resources.joinPath(this.fileSystemUserDataHome, relativePath); } private toUserDataResource(fileSystemResource: URI): URI | null { - if (resources.relativePath(this.userDataHome, fileSystemResource)) { - return fileSystemResource.with({ scheme: Schemas.userData }); + const userDataRelativePath = resources.relativePath(this.fileSystemUserDataHome, fileSystemResource); + if (userDataRelativePath) { + return resources.joinPath(this.userDataHome, userDataRelativePath); } - const relativePath = resources.relativePath(this.backupsHome, fileSystemResource); - if (relativePath) { - return resources.joinPath(this.userDataHome, BACKUPS, relativePath).with({ scheme: Schemas.userData }); + const backupRelativePath = resources.relativePath(this.fileSystemBackupsHome, fileSystemResource); + if (backupRelativePath) { + return resources.joinPath(this.userDataHome, BACKUPS, backupRelativePath); } return null; }