Skip to content

Commit

Permalink
Change profile options to use defaults or not (#152737)
Browse files Browse the repository at this point in the history
* - flip profile options to flags for using defaults
- adopt storage service to switch profile only when the storage location has changed

* 💄

Co-authored-by: Benjamin Pasero <[email protected]>
  • Loading branch information
sandy081 and bpasero authored Jun 21, 2022
1 parent dd2ca4c commit e52d6c4
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 90 deletions.
12 changes: 12 additions & 0 deletions src/vs/platform/storage/common/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,18 @@ export abstract class AbstractStorageService extends Disposable implements IStor
return this.switchToWorkspace(to, preserveData);
}

protected canSwitchProfile(from: IUserDataProfile, to: IUserDataProfile): boolean {
if (from.id === to.id) {
return false; // both profiles are same
}

if (to.isDefault || to.useDefaultFlags?.uiState === from.isDefault || from.useDefaultFlags?.uiState) {
return false; // both profiles are using default
}

return true;
}

protected switchData(oldStorage: Map<string, string>, newStorage: IStorage, scope: StorageScope, preserveData: boolean): void {
this.withPausedEmitters(() => {

Expand Down
4 changes: 4 additions & 0 deletions src/vs/platform/storage/electron-sandbox/storageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ export class NativeStorageService extends AbstractStorageService {
}

protected async switchToProfile(toProfile: IUserDataProfile, preserveData: boolean): Promise<void> {
if (this.profileStorageProfile && !this.canSwitchProfile(this.profileStorageProfile, toProfile)) {
return;
}

const oldProfileStorage = this.profileStorage;
const oldItems = oldProfileStorage.items;

Expand Down
51 changes: 25 additions & 26 deletions src/vs/platform/userDataProfile/common/userDataProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import { ILogService } from 'vs/platform/log/common/log';
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';

export type ProfileOptions = {
/**
* Flags to indicate whether to use the default profile or not.
*/
export type UseDefaultProfileFlags = {
settings?: boolean;
keybindings?: boolean;
tasks?: boolean;
Expand All @@ -25,15 +28,6 @@ export type ProfileOptions = {
uiState?: boolean;
};

export const DefaultOptions: ProfileOptions = {
settings: true,
keybindings: true,
tasks: true,
snippets: true,
extensions: true,
uiState: true
};

export interface IUserDataProfile {
readonly id: string;
readonly isDefault: boolean;
Expand All @@ -45,6 +39,7 @@ export interface IUserDataProfile {
readonly tasksResource: URI;
readonly snippetsHome: URI;
readonly extensionsResource: URI | undefined;
readonly useDefaultFlags?: UseDefaultProfileFlags;
}

export type CustomUserDataProfile = IUserDataProfile & { readonly extensionsResource: URI; readonly isDefault: false };
Expand Down Expand Up @@ -76,8 +71,8 @@ export interface IUserDataProfilesService {
readonly onDidChangeProfiles: Event<IUserDataProfile[]>;
readonly profiles: IUserDataProfile[];

newProfile(name: string, options?: ProfileOptions): CustomUserDataProfile;
createProfile(profile: IUserDataProfile, options: ProfileOptions, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile>;
newProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags): CustomUserDataProfile;
createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile>;
setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile>;
getProfile(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): IUserDataProfile;
removeProfile(profile: IUserDataProfile): Promise<void>;
Expand All @@ -100,20 +95,19 @@ export function reviveProfile(profile: UriDto<IUserDataProfile>, scheme: string)

export const EXTENSIONS_RESOURCE_NAME = 'extensions.json';

export function toUserDataProfile(name: string, location: URI, options: ProfileOptions, defaultProfile: true): IUserDataProfile;
export function toUserDataProfile(name: string, location: URI, options: ProfileOptions, defaultProfile: IUserDataProfile): CustomUserDataProfile;
export function toUserDataProfile(name: string, location: URI, options: ProfileOptions, defaultProfile: true | IUserDataProfile): IUserDataProfile {
export function toUserDataProfile(name: string, location: URI, useDefaultFlags?: UseDefaultProfileFlags): CustomUserDataProfile {
return {
id: hash(location.toString()).toString(16),
name: name,
location: location,
isDefault: defaultProfile === true,
globalStorageHome: defaultProfile === true || options.uiState ? joinPath(location, 'globalStorage') : defaultProfile.globalStorageHome,
settingsResource: defaultProfile === true || options.settings ? joinPath(location, 'settings.json') : defaultProfile.settingsResource,
keybindingsResource: defaultProfile === true || options.keybindings ? joinPath(location, 'keybindings.json') : defaultProfile.keybindingsResource,
tasksResource: defaultProfile === true || options.tasks ? joinPath(location, 'tasks.json') : defaultProfile.tasksResource,
snippetsHome: defaultProfile === true || options.snippets ? joinPath(location, 'snippets') : defaultProfile.snippetsHome,
extensionsResource: defaultProfile === true && !options.extensions ? undefined : joinPath(location, EXTENSIONS_RESOURCE_NAME),
isDefault: false,
globalStorageHome: joinPath(location, 'globalStorage'),
settingsResource: joinPath(location, 'settings.json'),
keybindingsResource: joinPath(location, 'keybindings.json'),
tasksResource: joinPath(location, 'tasks.json'),
snippetsHome: joinPath(location, 'snippets'),
extensionsResource: joinPath(location, EXTENSIONS_RESOURCE_NAME),
useDefaultFlags
};
}

Expand All @@ -138,14 +132,19 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
) {
super();
this.profilesHome = joinPath(this.environmentService.userRoamingDataHome, 'profiles');
this._defaultProfile = defaultProfile ? reviveProfile(defaultProfile, this.profilesHome.scheme) : toUserDataProfile(localize('defaultProfile', "Default"), environmentService.userRoamingDataHome, { ...DefaultOptions, extensions: false }, true);
this._defaultProfile = defaultProfile ? reviveProfile(defaultProfile, this.profilesHome.scheme) : this.createDefaultUserDataProfile(false);
}

newProfile(name: string, useDefaultFlags?: UseDefaultProfileFlags): CustomUserDataProfile {
return toUserDataProfile(name, joinPath(this.profilesHome, hash(name).toString(16)), useDefaultFlags);
}

newProfile(name: string, options: ProfileOptions = DefaultOptions): CustomUserDataProfile {
return toUserDataProfile(name, joinPath(this.profilesHome, hash(name).toString(16)), options, this.defaultProfile);
protected createDefaultUserDataProfile(extensions: boolean): IUserDataProfile {
const profile = toUserDataProfile(localize('defaultProfile', "Default"), this.environmentService.userRoamingDataHome);
return { ...profile, extensionsResource: extensions ? profile.extensionsResource : undefined };
}

createProfile(profile: IUserDataProfile, options: ProfileOptions, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> { throw new Error('Not implemented'); }
createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> { throw new Error('Not implemented'); }
setProfileForWorkspace(profile: IUserDataProfile, workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> { throw new Error('Not implemented'); }
getProfile(workspaceIdentifier: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): IUserDataProfile { throw new Error('Not implemented'); }
removeProfile(profile: IUserDataProfile): Promise<void> { throw new Error('Not implemented'); }
Expand Down
15 changes: 7 additions & 8 deletions src/vs/platform/userDataProfile/electron-main/userDataProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import { Emitter, Event } from 'vs/base/common/event';
import { revive } from 'vs/base/common/marshalling';
import { UriDto } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IFileService } from 'vs/platform/files/common/files';
import { refineServiceDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { IStateMainService } from 'vs/platform/state/electron-main/state';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { ProfileOptions, DefaultOptions, IUserDataProfile, IUserDataProfilesService, UserDataProfilesService, reviveProfile, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { UseDefaultProfileFlags, IUserDataProfile, IUserDataProfilesService, UserDataProfilesService, reviveProfile, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
import { Promises } from 'vs/base/common/async';

Expand Down Expand Up @@ -44,7 +43,7 @@ type UserDataProfilesObject = {
type StoredUserDataProfile = {
name: string;
location: URI;
options: ProfileOptions;
useDefaultFlags?: UseDefaultProfileFlags;
};

type StoredWorkspaceInfo = {
Expand All @@ -70,19 +69,19 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme
@IFileService fileService: IFileService,
@ILogService logService: ILogService,
) {
super(toUserDataProfile(localize('defaultProfile', "Default"), environmentService.userRoamingDataHome, { ...DefaultOptions, extensions: false }, true), environmentService, fileService, logService);
super(undefined, environmentService, fileService, logService);
}

init(): void {
if (this.storedProfiles.length) {
this._defaultProfile = toUserDataProfile(this.defaultProfile.name, this.defaultProfile.location, DefaultOptions, true);
this._defaultProfile = this.createDefaultUserDataProfile(true);
}
}

private _profilesObject: UserDataProfilesObject | undefined;
private get profilesObject(): UserDataProfilesObject {
if (!this._profilesObject) {
const profiles = this.storedProfiles.map<IUserDataProfile>(storedProfile => toUserDataProfile(storedProfile.name, storedProfile.location, storedProfile.options, this.defaultProfile));
const profiles = this.storedProfiles.map<IUserDataProfile>(storedProfile => toUserDataProfile(storedProfile.name, storedProfile.location, storedProfile.useDefaultFlags));
profiles.unshift(this.defaultProfile);
const workspaces = this.storedWorskpaceInfos.reduce((workspaces, workspaceProfileInfo) => {
const profile = profiles.find(p => this.uriIdentityService.extUri.isEqual(p.location, workspaceProfileInfo.profile));
Expand All @@ -106,7 +105,7 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme
return this.profilesObject.workspaces.get(this.getWorkspace(workspaceIdentifier)) ?? this.defaultProfile;
}

override async createProfile(profile: IUserDataProfile, options: ProfileOptions, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> {
override async createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> {
profile = reviveProfile(profile, this.profilesHome.scheme);
if (this.storedProfiles.some(p => p.name === profile.name)) {
throw new Error(`Profile with name ${profile.name} already exists`);
Expand All @@ -125,7 +124,7 @@ export class UserDataProfilesMainService extends UserDataProfilesService impleme
});
await Promises.settled(joiners);

const storedProfile: StoredUserDataProfile = { name: profile.name, location: profile.location, options };
const storedProfile: StoredUserDataProfile = { name: profile.name, location: profile.location, useDefaultFlags: profile.useDefaultFlags };
const storedProfiles = [...this.storedProfiles, storedProfile];
this.storedProfiles = storedProfiles;
if (workspaceIdentifier) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IFileService } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
import { ProfileOptions, IUserDataProfile, IUserDataProfilesService, reviveProfile, UserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
import { IUserDataProfile, IUserDataProfilesService, reviveProfile, UserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';

export class UserDataProfilesNativeService extends UserDataProfilesService implements IUserDataProfilesService {
Expand Down Expand Up @@ -36,8 +36,8 @@ export class UserDataProfilesNativeService extends UserDataProfilesService imple
}));
}

override async createProfile(profile: IUserDataProfile, options: ProfileOptions, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> {
const result = await this.channel.call<UriDto<IUserDataProfile>>('createProfile', [profile, options, workspaceIdentifier]);
override async createProfile(profile: IUserDataProfile, workspaceIdentifier?: ISingleFolderWorkspaceIdentifier | IWorkspaceIdentifier): Promise<IUserDataProfile> {
const result = await this.channel.call<UriDto<IUserDataProfile>>('createProfile', [profile, workspaceIdentifier]);
return reviveProfile(result, this.profilesHome.scheme);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { joinPath } from 'vs/base/common/resources';
import { VSBuffer } from 'vs/base/common/buffer';
import { RemoteAgentService } from 'vs/workbench/services/remote/browser/remoteAgentService';
import { getSingleFolderWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces';
import { DefaultOptions, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { hash } from 'vs/base/common/hash';
import { FilePolicyService } from 'vs/platform/policy/common/filePolicyService';
Expand Down Expand Up @@ -110,7 +110,7 @@ suite('ConfigurationEditingService', () => {
environmentService = TestEnvironmentService;
environmentService.policyFile = joinPath(workspaceFolder, 'policies.json');
instantiationService.stub(IEnvironmentService, environmentService);
const profile = toUserDataProfile('temp', environmentService.userRoamingDataHome, DefaultOptions, true);
const profile = toUserDataProfile('temp', environmentService.userRoamingDataHome);
userDataProfileService = new UserDataProfileService(profile, profile);
const remoteAgentService = disposables.add(instantiationService.createInstance(RemoteAgentService, null));
disposables.add(fileService.registerProvider(Schemas.vscodeUserData, disposables.add(new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.vscodeUserData, logService))));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import { RemoteAgentService } from 'vs/workbench/services/remote/browser/remoteA
import { RemoteAuthorityResolverService } from 'vs/platform/remote/browser/remoteAuthorityResolverService';
import { hash } from 'vs/base/common/hash';
import { TestProductService } from 'vs/workbench/test/common/workbenchTestServices';
import { DefaultOptions, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { NullPolicyService } from 'vs/platform/policy/common/policy';
import { FilePolicyService } from 'vs/platform/policy/common/filePolicyService';
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
Expand All @@ -68,7 +68,7 @@ export class ConfigurationCache implements IConfigurationCache {
const ROOT = URI.file('tests').with({ scheme: 'vscode-tests' });

function aUserDataProfileService(environmentService: IEnvironmentService): IUserDataProfileService {
const profile = toUserDataProfile('temp', environmentService.userRoamingDataHome, DefaultOptions, true);
const profile = toUserDataProfile('temp', environmentService.userRoamingDataHome);
return new UserDataProfileService(profile, profile);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { joinPath } from 'vs/base/common/resources';
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { VSBuffer } from 'vs/base/common/buffer';
import { DefaultOptions, toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { toUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { UserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfileService';
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';

Expand Down Expand Up @@ -66,7 +66,7 @@ suite('KeybindingsEditing', () => {
const configService = new TestConfigurationService();
configService.setUserConfiguration('files', { 'eol': '\n' });

const profile = toUserDataProfile('temp', environmentService.userRoamingDataHome, DefaultOptions, true);
const profile = toUserDataProfile('temp', environmentService.userRoamingDataHome);
userDataProfileService = new UserDataProfileService(profile, profile);

instantiationService = workbenchInstantiationService({
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/services/storage/browser/storageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ export class BrowserStorageService extends AbstractStorageService {
}

protected async switchToProfile(toProfile: IUserDataProfile, preserveData: boolean): Promise<void> {
if (this.profileStorageProfile && !this.canSwitchProfile(this.profileStorageProfile, toProfile)) {
return;
}

const oldProfileStorage = assertIsDefined(this.profileStorage);
const oldItems = oldProfileStorage.items;

Expand Down
Loading

0 comments on commit e52d6c4

Please sign in to comment.