mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Vscode merge (#4582)
* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd * fix issues with merges * bump node version in azpipe * replace license headers * remove duplicate launch task * fix build errors * fix build errors * fix tslint issues * working through package and linux build issues * more work * wip * fix packaged builds * working through linux build errors * wip * wip * wip * fix mac and linux file limits * iterate linux pipeline * disable editor typing * revert series to parallel * remove optimize vscode from linux * fix linting issues * revert testing change * add work round for new node * readd packaging for extensions * fix issue with angular not resolving decorator dependencies
This commit is contained in:
@@ -3,19 +3,10 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
export const FOLDER_CONFIG_FOLDER_NAME = '.azuredatastudio';
|
||||
export const FOLDER_SETTINGS_NAME = 'settings';
|
||||
export const FOLDER_SETTINGS_PATH = `${FOLDER_CONFIG_FOLDER_NAME}/${FOLDER_SETTINGS_NAME}.json`;
|
||||
|
||||
export const IWorkspaceConfigurationService = createDecorator<IWorkspaceConfigurationService>('configurationService');
|
||||
|
||||
export interface IWorkspaceConfigurationService extends IConfigurationService {
|
||||
}
|
||||
|
||||
export const defaultSettingsSchemaId = 'vscode://schemas/settings/default';
|
||||
export const userSettingsSchemaId = 'vscode://schemas/settings/user';
|
||||
export const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace';
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import * as encoding from 'vs/base/node/encoding';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { setProperty } from 'vs/base/common/jsonEdit';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
@@ -22,7 +21,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
|
||||
import { IConfigurationService, IConfigurationOverrides, keyFromOverrideIdentifier, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { FOLDER_SETTINGS_PATH, WORKSPACE_STANDALONE_CONFIGURATIONS, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { OVERRIDE_PROPERTY_PATTERN, IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
@@ -106,7 +105,7 @@ export interface IConfigurationEditingOptions {
|
||||
interface IConfigurationEditOperation extends IConfigurationValue {
|
||||
target: ConfigurationTarget;
|
||||
jsonPath: json.JSONPath;
|
||||
resource: URI;
|
||||
resource?: URI;
|
||||
workspaceStandAloneConfigurationKey?: string;
|
||||
|
||||
}
|
||||
@@ -158,7 +157,7 @@ export class ConfigurationEditingService {
|
||||
private async writeToBuffer(model: ITextModel, operation: IConfigurationEditOperation, save: boolean): Promise<any> {
|
||||
const edit = this.getEdits(model, operation)[0];
|
||||
if (edit && this.applyEditsToBuffer(edit, model) && save) {
|
||||
return this.textFileService.save(operation.resource, { skipSaveParticipants: true /* programmatic change */ });
|
||||
return this.textFileService.save(operation.resource!, { skipSaveParticipants: true /* programmatic change */ });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +174,7 @@ export class ConfigurationEditingService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private onError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides): void {
|
||||
private onError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides | undefined): void {
|
||||
switch (error.code) {
|
||||
case ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION:
|
||||
this.onInvalidConfigurationError(error, operation);
|
||||
@@ -196,7 +195,7 @@ export class ConfigurationEditingService {
|
||||
this.notificationService.prompt(Severity.Error, error.message,
|
||||
[{
|
||||
label: openStandAloneConfigurationActionLabel,
|
||||
run: () => this.openFile(operation.resource)
|
||||
run: () => this.openFile(operation.resource!)
|
||||
}]
|
||||
);
|
||||
} else {
|
||||
@@ -209,7 +208,7 @@ export class ConfigurationEditingService {
|
||||
}
|
||||
}
|
||||
|
||||
private onConfigurationFileDirtyError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides): void {
|
||||
private onConfigurationFileDirtyError(error: ConfigurationEditingError, operation: IConfigurationEditOperation, scopes: IConfigurationOverrides | undefined): void {
|
||||
const openStandAloneConfigurationActionLabel = operation.workspaceStandAloneConfigurationKey === TASKS_CONFIGURATION_KEY ? nls.localize('openTasksConfiguration', "Open Tasks Configuration")
|
||||
: operation.workspaceStandAloneConfigurationKey === LAUNCH_CONFIGURATION_KEY ? nls.localize('openLaunchConfiguration', "Open Launch Configuration")
|
||||
: null;
|
||||
@@ -218,13 +217,13 @@ export class ConfigurationEditingService {
|
||||
[{
|
||||
label: nls.localize('saveAndRetry', "Save and Retry"),
|
||||
run: () => {
|
||||
const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey;
|
||||
const key = operation.key ? `${operation.workspaceStandAloneConfigurationKey}.${operation.key}` : operation.workspaceStandAloneConfigurationKey!;
|
||||
this.writeConfiguration(operation.target, { key, value: operation.value }, <ConfigurationEditingOptions>{ force: true, scopes });
|
||||
}
|
||||
},
|
||||
{
|
||||
label: openStandAloneConfigurationActionLabel,
|
||||
run: () => this.openFile(operation.resource)
|
||||
run: () => this.openFile(operation.resource!)
|
||||
}]
|
||||
);
|
||||
} else {
|
||||
@@ -296,7 +295,13 @@ export class ConfigurationEditingService {
|
||||
case ConfigurationTarget.WORKSPACE:
|
||||
return nls.localize('errorInvalidConfigurationWorkspace', "Unable to write into workspace settings. Please open the workspace settings to correct errors/warnings in the file and try again.");
|
||||
case ConfigurationTarget.WORKSPACE_FOLDER:
|
||||
const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name;
|
||||
let workspaceFolderName: string = '<<unknown>>';
|
||||
if (operation.resource) {
|
||||
const folder = this.contextService.getWorkspaceFolder(operation.resource);
|
||||
if (folder) {
|
||||
workspaceFolderName = folder.name;
|
||||
}
|
||||
}
|
||||
return nls.localize('errorInvalidConfigurationFolder', "Unable to write into folder settings. Please open the '{0}' folder settings to correct errors/warnings in it and try again.", workspaceFolderName);
|
||||
}
|
||||
return '';
|
||||
@@ -314,7 +319,13 @@ export class ConfigurationEditingService {
|
||||
case ConfigurationTarget.WORKSPACE:
|
||||
return nls.localize('errorConfigurationFileDirtyWorkspace', "Unable to write into workspace settings because the file is dirty. Please save the workspace settings file first and then try again.");
|
||||
case ConfigurationTarget.WORKSPACE_FOLDER:
|
||||
const workspaceFolderName = this.contextService.getWorkspaceFolder(operation.resource).name;
|
||||
let workspaceFolderName: string = '<<unknown>>';
|
||||
if (operation.resource) {
|
||||
const folder = this.contextService.getWorkspaceFolder(operation.resource);
|
||||
if (folder) {
|
||||
workspaceFolderName = folder.name;
|
||||
}
|
||||
}
|
||||
return nls.localize('errorConfigurationFileDirtyFolder', "Unable to write into folder settings because the file is dirty. Please save the '{0}' folder settings file first and then try again.", workspaceFolderName);
|
||||
}
|
||||
return '';
|
||||
@@ -352,10 +363,10 @@ export class ConfigurationEditingService {
|
||||
return setProperty(model.getValue(), jsonPath, value, { tabSize, insertSpaces, eol });
|
||||
}
|
||||
|
||||
private async resolveModelReference(resource: URI): Promise<IReference<ITextEditorModel>> {
|
||||
private async resolveModelReference(resource: URI): Promise<IReference<IResolvedTextEditorModel>> {
|
||||
const exists = await this.fileService.existsFile(resource);
|
||||
if (!exists) {
|
||||
await this.fileService.updateContent(resource, '{}', { encoding: encoding.UTF8 });
|
||||
await this.fileService.updateContent(resource, '{}', { encoding: 'utf8' });
|
||||
}
|
||||
return this.textModelResolverService.createModelReference(resource);
|
||||
}
|
||||
@@ -371,7 +382,7 @@ export class ConfigurationEditingService {
|
||||
return parseErrors.length > 0;
|
||||
}
|
||||
|
||||
private resolveAndValidate(target: ConfigurationTarget, operation: IConfigurationEditOperation, checkDirty: boolean, overrides: IConfigurationOverrides): Promise<IReference<ITextEditorModel>> {
|
||||
private resolveAndValidate(target: ConfigurationTarget, operation: IConfigurationEditOperation, checkDirty: boolean, overrides: IConfigurationOverrides): Promise<IReference<IResolvedTextEditorModel>> {
|
||||
|
||||
// Any key must be a known setting from the registry (unless this is a standalone config)
|
||||
if (!operation.workspaceStandAloneConfigurationKey) {
|
||||
@@ -420,6 +431,10 @@ export class ConfigurationEditingService {
|
||||
}
|
||||
}
|
||||
|
||||
if (!operation.resource) {
|
||||
return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_TARGET, target, operation);
|
||||
}
|
||||
|
||||
return this.resolveModelReference(operation.resource)
|
||||
.then(reference => {
|
||||
const model = reference.object.textEditorModel;
|
||||
@@ -447,14 +462,14 @@ export class ConfigurationEditingService {
|
||||
// Check for prefix
|
||||
if (config.key === key) {
|
||||
const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key] : [];
|
||||
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target };
|
||||
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource: resource || undefined, workspaceStandAloneConfigurationKey: key, target };
|
||||
}
|
||||
|
||||
// Check for prefix.<setting>
|
||||
const keyPrefix = `${key}.`;
|
||||
if (config.key.indexOf(keyPrefix) === 0) {
|
||||
const jsonPath = this.isWorkspaceConfigurationResource(resource) ? [key, config.key.substr(keyPrefix.length)] : [config.key.substr(keyPrefix.length)];
|
||||
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource, workspaceStandAloneConfigurationKey: key, target };
|
||||
return { key: jsonPath[jsonPath.length - 1], jsonPath, value: config.value, resource: resource || undefined, workspaceStandAloneConfigurationKey: key, target };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -469,15 +484,15 @@ export class ConfigurationEditingService {
|
||||
if (this.isWorkspaceConfigurationResource(resource)) {
|
||||
jsonPath = ['settings', ...jsonPath];
|
||||
}
|
||||
return { key, jsonPath, value: config.value, resource, target };
|
||||
return { key, jsonPath, value: config.value, resource: resource || undefined, target };
|
||||
}
|
||||
|
||||
private isWorkspaceConfigurationResource(resource: URI): boolean {
|
||||
private isWorkspaceConfigurationResource(resource: URI | null | undefined): boolean {
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
return workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath;
|
||||
return !!(workspace.configuration && resource && workspace.configuration.fsPath === resource.fsPath);
|
||||
}
|
||||
|
||||
private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI): URI {
|
||||
private getConfigurationFileResource(target: ConfigurationTarget, relativePath: string, resource: URI | null | undefined): URI | null {
|
||||
if (target === ConfigurationTarget.USER) {
|
||||
return URI.file(this.environmentService.appSettingsPath);
|
||||
}
|
||||
@@ -489,7 +504,7 @@ export class ConfigurationEditingService {
|
||||
|
||||
if (target === ConfigurationTarget.WORKSPACE) {
|
||||
if (workbenchState === WorkbenchState.WORKSPACE) {
|
||||
return workspace.configuration;
|
||||
return workspace.configuration || null;
|
||||
}
|
||||
if (workbenchState === WorkbenchState.FOLDER) {
|
||||
return workspace.folders[0].toResource(relativePath);
|
||||
@@ -136,11 +136,11 @@ export class Configuration extends BaseConfiguration {
|
||||
folders: ResourceMap<ConfigurationModel>,
|
||||
memoryConfiguration: ConfigurationModel,
|
||||
memoryConfigurationByResource: ResourceMap<ConfigurationModel>,
|
||||
private readonly _workspace: Workspace) {
|
||||
private readonly _workspace?: Workspace) {
|
||||
super(defaults, user, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource);
|
||||
}
|
||||
|
||||
getValue(key: string, overrides: IConfigurationOverrides = {}): any {
|
||||
getValue(key: string | undefined, overrides: IConfigurationOverrides = {}): any {
|
||||
return super.getValue(key, overrides, this._workspace);
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ export class AllKeysConfigurationChangeEvent extends AbstractConfigurationChange
|
||||
|
||||
export class WorkspaceConfigurationChangeEvent implements IConfigurationChangeEvent {
|
||||
|
||||
constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace) { }
|
||||
constructor(private configurationChangeEvent: IConfigurationChangeEvent, private workspace: Workspace | undefined) { }
|
||||
|
||||
get changedConfiguration(): IConfigurationModel {
|
||||
return this.configurationChangeEvent.changedConfiguration;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import * as encoding from 'vs/base/node/encoding';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { setProperty } from 'vs/base/common/jsonEdit';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
@@ -17,9 +16,10 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { ITextModelService, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
|
||||
import { IJSONEditingService, IJSONValue, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
|
||||
export class JSONEditingService implements IJSONEditingService {
|
||||
|
||||
@@ -83,10 +83,10 @@ export class JSONEditingService implements IJSONEditingService {
|
||||
return setProperty(model.getValue(), [key], value, { tabSize, insertSpaces, eol });
|
||||
}
|
||||
|
||||
private async resolveModelReference(resource: URI): Promise<IReference<ITextEditorModel>> {
|
||||
private async resolveModelReference(resource: URI): Promise<IReference<IResolvedTextEditorModel>> {
|
||||
const exists = await this.fileService.existsFile(resource);
|
||||
if (!exists) {
|
||||
await this.fileService.updateContent(resource, '{}', { encoding: encoding.UTF8 });
|
||||
await this.fileService.updateContent(resource, '{}', { encoding: 'utf8' });
|
||||
}
|
||||
return this.textModelResolverService.createModelReference(resource);
|
||||
}
|
||||
@@ -97,18 +97,18 @@ export class JSONEditingService implements IJSONEditingService {
|
||||
return parseErrors.length > 0;
|
||||
}
|
||||
|
||||
private resolveAndValidate(resource: URI, checkDirty: boolean): Promise<IReference<ITextEditorModel>> {
|
||||
private resolveAndValidate(resource: URI, checkDirty: boolean): Promise<IReference<IResolvedTextEditorModel>> {
|
||||
return this.resolveModelReference(resource)
|
||||
.then(reference => {
|
||||
const model = reference.object.textEditorModel;
|
||||
|
||||
if (this.hasParseErrors(model)) {
|
||||
return this.reject<IReference<ITextEditorModel>>(JSONEditingErrorCode.ERROR_INVALID_FILE);
|
||||
return this.reject<IReference<IResolvedTextEditorModel>>(JSONEditingErrorCode.ERROR_INVALID_FILE);
|
||||
}
|
||||
|
||||
// Target cannot be dirty if not writing into buffer
|
||||
if (checkDirty && this.textFileService.isDirty(resource)) {
|
||||
return this.reject<IReference<ITextEditorModel>>(JSONEditingErrorCode.ERROR_FILE_DIRTY);
|
||||
return this.reject<IReference<IResolvedTextEditorModel>>(JSONEditingErrorCode.ERROR_FILE_DIRTY);
|
||||
}
|
||||
return reference;
|
||||
});
|
||||
@@ -131,3 +131,5 @@ export class JSONEditingService implements IJSONEditingService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IJSONEditingService, JSONEditingService, true);
|
||||
@@ -5,25 +5,23 @@
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { createHash } from 'crypto';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as collections from 'vs/base/common/collections';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler, Delayer } from 'vs/base/common/async';
|
||||
import { FileChangeType, FileChangesEvent, IContent, IFileService } from 'vs/platform/files/common/files';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { WorkspaceConfigurationModelParser, FolderSettingsModelParser, StandaloneConfigurationModelParser } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { FOLDER_SETTINGS_PATH, TASKS_CONFIGURATION_KEY, FOLDER_SETTINGS_NAME, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import * as extfs from 'vs/base/node/extfs';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
|
||||
import { WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { relative } from 'path';
|
||||
import { extname, join } from 'vs/base/common/path';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
@@ -37,7 +35,7 @@ export interface IWorkspaceIdentifier {
|
||||
export class WorkspaceConfiguration extends Disposable {
|
||||
|
||||
private readonly _cachedConfiguration: CachedWorkspaceConfiguration;
|
||||
private _workspaceConfiguration: IWorkspaceConfiguration | null;
|
||||
private _workspaceConfiguration: IWorkspaceConfiguration;
|
||||
private _workspaceIdentifier: IWorkspaceIdentifier | null = null;
|
||||
private _fileService: IFileService | null = null;
|
||||
|
||||
@@ -99,11 +97,16 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
if (this._workspaceIdentifier) {
|
||||
if (this._fileService) {
|
||||
if (!(this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration)) {
|
||||
dispose(this._workspaceConfiguration);
|
||||
const nodeBasedWorkspaceConfiguration = this._workspaceConfiguration instanceof NodeBasedWorkspaceConfiguration ? this._workspaceConfiguration : undefined;
|
||||
this._workspaceConfiguration = new FileServiceBasedWorkspaceConfiguration(this._fileService, nodeBasedWorkspaceConfiguration);
|
||||
const oldWorkspaceConfiguration = this._workspaceConfiguration;
|
||||
this._workspaceConfiguration = new FileServiceBasedWorkspaceConfiguration(this._fileService, oldWorkspaceConfiguration);
|
||||
this._register(this._workspaceConfiguration.onDidChange(e => this.onDidWorkspaceConfigurationChange()));
|
||||
return !nodeBasedWorkspaceConfiguration;
|
||||
if (oldWorkspaceConfiguration instanceof CachedWorkspaceConfiguration) {
|
||||
this.updateCache();
|
||||
return true;
|
||||
} else {
|
||||
dispose(oldWorkspaceConfiguration);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -127,7 +130,7 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
private updateCache(): Promise<void> {
|
||||
if (this._workspaceIdentifier && this._workspaceIdentifier.configPath.scheme !== Schemas.file && this._workspaceConfiguration instanceof FileServiceBasedWorkspaceConfiguration) {
|
||||
return this._workspaceConfiguration.load(this._workspaceIdentifier)
|
||||
.then(() => this._cachedConfiguration.updateWorkspace(this._workspaceIdentifier, this._workspaceConfiguration.getConfigurationModel()));
|
||||
.then(() => this._cachedConfiguration.updateWorkspace(this._workspaceIdentifier!, this._workspaceConfiguration.getConfigurationModel()));
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
@@ -135,6 +138,9 @@ export class WorkspaceConfiguration extends Disposable {
|
||||
|
||||
interface IWorkspaceConfiguration extends IDisposable {
|
||||
readonly onDidChange: Event<void>;
|
||||
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
|
||||
workspaceSettings: ConfigurationModel;
|
||||
workspaceIdentifier: IWorkspaceIdentifier | null;
|
||||
load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void>;
|
||||
getConfigurationModel(): ConfigurationModel;
|
||||
getFolders(): IStoredWorkspaceFolder[];
|
||||
@@ -144,18 +150,18 @@ interface IWorkspaceConfiguration extends IDisposable {
|
||||
|
||||
abstract class AbstractWorkspaceConfiguration extends Disposable implements IWorkspaceConfiguration {
|
||||
|
||||
private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
|
||||
private _workspaceSettings: ConfigurationModel;
|
||||
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
|
||||
workspaceSettings: ConfigurationModel;
|
||||
private _workspaceIdentifier: IWorkspaceIdentifier | null = null;
|
||||
|
||||
protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
constructor(from?: AbstractWorkspaceConfiguration) {
|
||||
constructor(from?: IWorkspaceConfiguration) {
|
||||
super();
|
||||
|
||||
this._workspaceConfigurationModelParser = from ? from._workspaceConfigurationModelParser : new WorkspaceConfigurationModelParser('');
|
||||
this._workspaceSettings = new ConfigurationModel();
|
||||
this.workspaceConfigurationModelParser = from ? from.workspaceConfigurationModelParser : new WorkspaceConfigurationModelParser('');
|
||||
this.workspaceSettings = from ? from.workspaceSettings : new ConfigurationModel();
|
||||
}
|
||||
|
||||
get workspaceIdentifier(): IWorkspaceIdentifier | null {
|
||||
@@ -166,32 +172,32 @@ abstract class AbstractWorkspaceConfiguration extends Disposable implements IWor
|
||||
this._workspaceIdentifier = workspaceIdentifier;
|
||||
return this.loadWorkspaceConfigurationContents(workspaceIdentifier)
|
||||
.then(contents => {
|
||||
this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(workspaceIdentifier.id);
|
||||
this._workspaceConfigurationModelParser.parse(contents);
|
||||
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(workspaceIdentifier.id);
|
||||
this.workspaceConfigurationModelParser.parse(contents);
|
||||
this.consolidate();
|
||||
});
|
||||
}
|
||||
|
||||
getConfigurationModel(): ConfigurationModel {
|
||||
return this._workspaceConfigurationModelParser.configurationModel;
|
||||
return this.workspaceConfigurationModelParser.configurationModel;
|
||||
}
|
||||
|
||||
getFolders(): IStoredWorkspaceFolder[] {
|
||||
return this._workspaceConfigurationModelParser.folders;
|
||||
return this.workspaceConfigurationModelParser.folders;
|
||||
}
|
||||
|
||||
getWorkspaceSettings(): ConfigurationModel {
|
||||
return this._workspaceSettings;
|
||||
return this.workspaceSettings;
|
||||
}
|
||||
|
||||
reprocessWorkspaceSettings(): ConfigurationModel {
|
||||
this._workspaceConfigurationModelParser.reprocessWorkspaceSettings();
|
||||
this.workspaceConfigurationModelParser.reprocessWorkspaceSettings();
|
||||
this.consolidate();
|
||||
return this.getWorkspaceSettings();
|
||||
}
|
||||
|
||||
private consolidate(): void {
|
||||
this._workspaceSettings = this._workspaceConfigurationModelParser.settingsModel.merge(this._workspaceConfigurationModelParser.launchModel);
|
||||
this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel);
|
||||
}
|
||||
|
||||
protected abstract loadWorkspaceConfigurationContents(workspaceIdentifier: IWorkspaceIdentifier): Promise<string>;
|
||||
@@ -214,15 +220,33 @@ class FileServiceBasedWorkspaceConfiguration extends AbstractWorkspaceConfigurat
|
||||
private workspaceConfig: URI | null = null;
|
||||
private readonly reloadConfigurationScheduler: RunOnceScheduler;
|
||||
|
||||
constructor(private fileService: IFileService, from?: AbstractWorkspaceConfiguration) {
|
||||
constructor(private fileService: IFileService, from?: IWorkspaceConfiguration) {
|
||||
super(from);
|
||||
this.workspaceConfig = from ? from.workspaceIdentifier.configPath : null;
|
||||
this.workspaceConfig = from && from.workspaceIdentifier ? from.workspaceIdentifier.configPath : null;
|
||||
this._register(fileService.onFileChanges(e => this.handleWorkspaceFileEvents(e)));
|
||||
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this._onDidChange.fire(), 50));
|
||||
this.watchWorkspaceConfigurationFile();
|
||||
this._register(toDisposable(() => this.unWatchWorkspaceConfigurtionFile()));
|
||||
}
|
||||
|
||||
private watchWorkspaceConfigurationFile(): void {
|
||||
if (this.workspaceConfig) {
|
||||
this.fileService.watchFileChanges(this.workspaceConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private unWatchWorkspaceConfigurtionFile(): void {
|
||||
if (this.workspaceConfig) {
|
||||
this.fileService.unwatchFileChanges(this.workspaceConfig);
|
||||
}
|
||||
}
|
||||
|
||||
protected loadWorkspaceConfigurationContents(workspaceIdentifier: IWorkspaceIdentifier): Promise<string> {
|
||||
this.workspaceConfig = workspaceIdentifier.configPath;
|
||||
if (!(this.workspaceConfig && resources.isEqual(this.workspaceConfig, workspaceIdentifier.configPath))) {
|
||||
this.unWatchWorkspaceConfigurtionFile();
|
||||
this.workspaceConfig = workspaceIdentifier.configPath;
|
||||
this.watchWorkspaceConfigurationFile();
|
||||
}
|
||||
return this.fileService.resolveContent(this.workspaceConfig)
|
||||
.then(content => content.value, e => {
|
||||
errors.onUnexpectedError(e);
|
||||
@@ -254,39 +278,43 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
|
||||
|
||||
private cachedWorkspacePath: string;
|
||||
private cachedConfigurationPath: string;
|
||||
private _workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
|
||||
private _workspaceSettings: ConfigurationModel;
|
||||
workspaceConfigurationModelParser: WorkspaceConfigurationModelParser;
|
||||
workspaceSettings: ConfigurationModel;
|
||||
|
||||
constructor(private environmentService: IEnvironmentService) {
|
||||
super();
|
||||
this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser('');
|
||||
this._workspaceSettings = new ConfigurationModel();
|
||||
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser('');
|
||||
this.workspaceSettings = new ConfigurationModel();
|
||||
}
|
||||
|
||||
load(workspaceIdentifier: IWorkspaceIdentifier): Promise<void> {
|
||||
this.createPaths(workspaceIdentifier);
|
||||
return pfs.readFile(this.cachedConfigurationPath)
|
||||
.then(contents => {
|
||||
this._workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this.cachedConfigurationPath);
|
||||
this._workspaceConfigurationModelParser.parse(contents.toString());
|
||||
this._workspaceSettings = this._workspaceConfigurationModelParser.settingsModel.merge(this._workspaceConfigurationModelParser.launchModel);
|
||||
}, () => null);
|
||||
this.workspaceConfigurationModelParser = new WorkspaceConfigurationModelParser(this.cachedConfigurationPath);
|
||||
this.workspaceConfigurationModelParser.parse(contents.toString());
|
||||
this.workspaceSettings = this.workspaceConfigurationModelParser.settingsModel.merge(this.workspaceConfigurationModelParser.launchModel);
|
||||
}, () => { });
|
||||
}
|
||||
|
||||
get workspaceIdentifier(): IWorkspaceIdentifier | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
getConfigurationModel(): ConfigurationModel {
|
||||
return this._workspaceConfigurationModelParser.configurationModel;
|
||||
return this.workspaceConfigurationModelParser.configurationModel;
|
||||
}
|
||||
|
||||
getFolders(): IStoredWorkspaceFolder[] {
|
||||
return this._workspaceConfigurationModelParser.folders;
|
||||
return this.workspaceConfigurationModelParser.folders;
|
||||
}
|
||||
|
||||
getWorkspaceSettings(): ConfigurationModel {
|
||||
return this._workspaceSettings;
|
||||
return this.workspaceSettings;
|
||||
}
|
||||
|
||||
reprocessWorkspaceSettings(): ConfigurationModel {
|
||||
return this._workspaceSettings;
|
||||
return this.workspaceSettings;
|
||||
}
|
||||
|
||||
async updateWorkspace(workspaceIdentifier: IWorkspaceIdentifier, configurationModel: ConfigurationModel): Promise<void> {
|
||||
@@ -297,7 +325,7 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
|
||||
if (!exists) {
|
||||
await pfs.mkdirp(this.cachedWorkspacePath);
|
||||
}
|
||||
const raw = JSON.stringify(configurationModel.toJSON());
|
||||
const raw = JSON.stringify(configurationModel.toJSON().contents);
|
||||
await pfs.writeFile(this.cachedConfigurationPath, raw);
|
||||
} else {
|
||||
pfs.rimraf(this.cachedWorkspacePath);
|
||||
@@ -308,8 +336,8 @@ class CachedWorkspaceConfiguration extends Disposable implements IWorkspaceConfi
|
||||
}
|
||||
|
||||
private createPaths(workspaceIdentifier: IWorkspaceIdentifier) {
|
||||
this.cachedWorkspacePath = paths.join(this.environmentService.userDataPath, 'CachedConfigurations', 'workspaces', workspaceIdentifier.id);
|
||||
this.cachedConfigurationPath = paths.join(this.cachedWorkspacePath, 'workspace.json');
|
||||
this.cachedWorkspacePath = join(this.environmentService.userDataPath, 'CachedConfigurations', 'workspaces', workspaceIdentifier.id);
|
||||
this.cachedConfigurationPath = join(this.cachedWorkspacePath, 'workspace.json');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,7 +499,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
|
||||
}
|
||||
|
||||
private doLoadFolderConfigurationContents(): Promise<Array<{ resource: URI, value: string }>> {
|
||||
const workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: Promise<IContent> } = Object.create(null);
|
||||
const workspaceFilePathToConfiguration: { [relativeWorkspacePath: string]: Promise<IContent | undefined> } = Object.create(null);
|
||||
const bulkContentFetchromise = Promise.resolve(this.fileService.resolveFile(this.folderConfigurationPath))
|
||||
.then(stat => {
|
||||
if (stat.isDirectory && stat.children) {
|
||||
@@ -486,7 +514,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
|
||||
}
|
||||
}).then(undefined, err => [] /* never fail this call */);
|
||||
|
||||
return bulkContentFetchromise.then(() => Promise.all(collections.values(workspaceFilePathToConfiguration)));
|
||||
return bulkContentFetchromise.then(() => Promise.all<IContent>(collections.values(workspaceFilePathToConfiguration))).then(contents => contents.filter(content => content !== undefined));
|
||||
}
|
||||
|
||||
private handleWorkspaceFileEvents(event: FileChangesEvent): void {
|
||||
@@ -497,7 +525,7 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
|
||||
for (let i = 0, len = events.length; i < len; i++) {
|
||||
const resource = events[i].resource;
|
||||
const basename = resources.basename(resource);
|
||||
const isJson = paths.extname(basename) === '.json';
|
||||
const isJson = extname(basename) === '.json';
|
||||
const isDeletedSettingsFolder = (events[i].type === FileChangeType.DELETED && basename === this.configFolderRelativePath);
|
||||
|
||||
if (!isJson && !isDeletedSettingsFolder) {
|
||||
@@ -529,17 +557,11 @@ export class FileServiceBasedFolderConfiguration extends AbstractFolderConfigura
|
||||
}
|
||||
}
|
||||
|
||||
private toFolderRelativePath(resource: URI): string | null {
|
||||
if (resource.scheme === Schemas.file) {
|
||||
if (paths.isEqualOrParent(resource.fsPath, this.folderConfigurationPath.fsPath, !isLinux /* ignorecase */)) {
|
||||
return paths.normalize(relative(this.folderConfigurationPath.fsPath, resource.fsPath));
|
||||
}
|
||||
} else {
|
||||
if (resources.isEqualOrParent(resource, this.folderConfigurationPath)) {
|
||||
return paths.normalize(relative(this.folderConfigurationPath.path, resource.path));
|
||||
}
|
||||
private toFolderRelativePath(resource: URI): string | undefined {
|
||||
if (resources.isEqualOrParent(resource, this.folderConfigurationPath)) {
|
||||
return resources.relativePath(this.folderConfigurationPath, resource);
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,8 +581,8 @@ export class CachedFolderConfiguration extends Disposable implements IFolderConf
|
||||
configFolderRelativePath: string,
|
||||
environmentService: IEnvironmentService) {
|
||||
super();
|
||||
this.cachedFolderPath = paths.join(environmentService.userDataPath, 'CachedConfigurations', 'folders', createHash('md5').update(paths.join(folder.path, configFolderRelativePath)).digest('hex'));
|
||||
this.cachedConfigurationPath = paths.join(this.cachedFolderPath, 'configuration.json');
|
||||
this.cachedFolderPath = join(environmentService.userDataPath, 'CachedConfigurations', 'folders', createHash('md5').update(join(folder.path, configFolderRelativePath)).digest('hex'));
|
||||
this.cachedConfigurationPath = join(this.cachedFolderPath, 'configuration.json');
|
||||
this.configurationModel = new ConfigurationModel();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { equals, deepClone } from 'vs/base/common/objects';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
import { Queue, Barrier } from 'vs/base/common/async';
|
||||
import { writeFile } from 'vs/base/node/pfs';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { IWorkspaceContextService, Workspace, WorkbenchState, IWorkspaceFolder, toWorkspaceFolders, IWorkspaceFoldersChangeEvent, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
@@ -17,34 +17,32 @@ import { isLinux } from 'vs/base/common/platform';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ConfigurationChangeEvent, ConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides, keyFromOverrideIdentifier, isConfigurationOverrides, IConfigurationData, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, WorkspaceConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { IWorkspaceConfigurationService, FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationNode, IConfigurationRegistry, Extensions, IConfigurationPropertySchema, allSettings, windowSettings, resourceSettings, applicationSettings } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import product from 'vs/platform/node/product';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditingService';
|
||||
import { WorkspaceConfiguration, FolderConfiguration } from 'vs/workbench/services/configuration/node/configuration';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
|
||||
import { UserConfiguration } from 'vs/platform/configuration/node/configuration';
|
||||
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
|
||||
import { localize } from 'vs/nls';
|
||||
import { isEqual, dirname } from 'vs/base/common/resources';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService {
|
||||
export class WorkspaceService extends Disposable implements IConfigurationService, IWorkspaceContextService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
|
||||
private workspace: Workspace;
|
||||
private resolvePromise: Promise<void>;
|
||||
private resolveCallback: () => void;
|
||||
private completeWorkspaceBarrier: Barrier;
|
||||
private _configuration: Configuration;
|
||||
private defaultConfiguration: DefaultConfigurationModel;
|
||||
private userConfiguration: UserConfiguration;
|
||||
@@ -72,7 +70,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
constructor(private environmentService: IEnvironmentService, private workspaceSettingsRootFolder: string = FOLDER_CONFIG_FOLDER_NAME) {
|
||||
super();
|
||||
|
||||
this.resolvePromise = new Promise(c => this.resolveCallback = c);
|
||||
this.completeWorkspaceBarrier = new Barrier();
|
||||
this.defaultConfiguration = new DefaultConfigurationModel();
|
||||
this.userConfiguration = this._register(new UserConfiguration(environmentService.appSettingsPath));
|
||||
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(environmentService));
|
||||
@@ -88,7 +86,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
// Workspace Context Service Impl
|
||||
|
||||
public getCompleteWorkspace(): Promise<Workspace> {
|
||||
return this.resolvePromise.then(() => this.getWorkspace());
|
||||
return this.completeWorkspaceBarrier.wait().then(() => this.getWorkspace());
|
||||
}
|
||||
|
||||
public getWorkspace(): Workspace {
|
||||
@@ -110,7 +108,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
return WorkbenchState.EMPTY;
|
||||
}
|
||||
|
||||
public getWorkspaceFolder(resource: URI): IWorkspaceFolder {
|
||||
public getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {
|
||||
return this.workspace.getFolder(resource);
|
||||
}
|
||||
|
||||
@@ -154,7 +152,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
|
||||
// Remove first (if any)
|
||||
let currentWorkspaceFolders = this.getWorkspace().folders;
|
||||
let newStoredFolders: IStoredWorkspaceFolder[] = currentWorkspaceFolders.map(f => f.raw).filter((folder, index) => {
|
||||
let newStoredFolders: IStoredWorkspaceFolder[] = currentWorkspaceFolders.map(f => f.raw).filter((folder, index): folder is IStoredWorkspaceFolder => {
|
||||
if (!isStoredWorkspaceFolder(folder)) {
|
||||
return true; // keep entries which are unrelated
|
||||
}
|
||||
@@ -162,44 +160,26 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
return !this.contains(foldersToRemove, currentWorkspaceFolders[index].uri); // keep entries which are unrelated
|
||||
});
|
||||
|
||||
const slashForPath = useSlashForPath(newStoredFolders);
|
||||
|
||||
foldersHaveChanged = currentWorkspaceFolders.length !== newStoredFolders.length;
|
||||
|
||||
// Add afterwards (if any)
|
||||
if (foldersToAdd.length) {
|
||||
|
||||
// Recompute current workspace folders if we have folders to add
|
||||
const workspaceConfigFolder = dirname(this.getWorkspace().configuration);
|
||||
const workspaceConfigFolder = dirname(this.getWorkspace().configuration!);
|
||||
currentWorkspaceFolders = toWorkspaceFolders(newStoredFolders, workspaceConfigFolder);
|
||||
const currentWorkspaceFolderUris = currentWorkspaceFolders.map(folder => folder.uri);
|
||||
|
||||
const storedFoldersToAdd: IStoredWorkspaceFolder[] = [];
|
||||
|
||||
foldersToAdd.forEach(folderToAdd => {
|
||||
if (this.contains(currentWorkspaceFolderUris, folderToAdd.uri)) {
|
||||
const folderURI = folderToAdd.uri;
|
||||
if (this.contains(currentWorkspaceFolderUris, folderURI)) {
|
||||
return; // already existing
|
||||
}
|
||||
|
||||
let storedFolder: IStoredWorkspaceFolder;
|
||||
|
||||
// File resource: use "path" property
|
||||
if (folderToAdd.uri.scheme === Schemas.file) {
|
||||
storedFolder = {
|
||||
path: massageFolderPathForWorkspace(folderToAdd.uri.fsPath, workspaceConfigFolder, newStoredFolders)
|
||||
};
|
||||
}
|
||||
|
||||
// Any other resource: use "uri" property
|
||||
else {
|
||||
storedFolder = {
|
||||
uri: folderToAdd.uri.toString(true)
|
||||
};
|
||||
}
|
||||
|
||||
if (folderToAdd.name) {
|
||||
storedFolder.name = folderToAdd.name;
|
||||
}
|
||||
|
||||
storedFoldersToAdd.push(storedFolder);
|
||||
storedFoldersToAdd.push(getStoredWorkspaceFolder(folderURI, folderToAdd.name, workspaceConfigFolder, slashForPath));
|
||||
});
|
||||
|
||||
// Apply to array of newStoredFolders
|
||||
@@ -266,7 +246,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
const overrides = isConfigurationOverrides(arg3) ? arg3 : undefined;
|
||||
const target = this.deriveConfigurationTarget(key, value, overrides, overrides ? arg4 : arg3);
|
||||
return target ? this.writeConfigurationValue(key, value, target, overrides, donotNotifyError)
|
||||
: Promise.resolve(null);
|
||||
: Promise.resolve();
|
||||
}
|
||||
|
||||
reloadConfiguration(folder?: IWorkspaceFolder, key?: string): Promise<void> {
|
||||
@@ -324,7 +304,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
for (const workspaceFolder of changedWorkspaceFolders) {
|
||||
this.onWorkspaceFolderConfigurationChanged(workspaceFolder);
|
||||
}
|
||||
this.resolveCallback();
|
||||
this.releaseWorkspaceBarrier();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -346,12 +326,16 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
}
|
||||
|
||||
private createMultiFolderWorkspace(workspaceIdentifier: IWorkspaceIdentifier): Promise<Workspace> {
|
||||
return this.workspaceConfiguration.load({ id: workspaceIdentifier.id, configPath: URI.file(workspaceIdentifier.configPath) })
|
||||
return this.workspaceConfiguration.load({ id: workspaceIdentifier.id, configPath: workspaceIdentifier.configPath })
|
||||
.then(() => {
|
||||
const workspaceConfigPath = URI.file(workspaceIdentifier.configPath);
|
||||
const workspaceConfigPath = workspaceIdentifier.configPath;
|
||||
const workspaceFolders = toWorkspaceFolders(this.workspaceConfiguration.getFolders(), dirname(workspaceConfigPath));
|
||||
const workspaceId = workspaceIdentifier.id;
|
||||
return new Workspace(workspaceId, workspaceFolders, workspaceConfigPath);
|
||||
const workspace = new Workspace(workspaceId, workspaceFolders, workspaceConfigPath);
|
||||
if (workspace.configuration!.scheme === Schemas.file) {
|
||||
this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is from disk.
|
||||
}
|
||||
return workspace;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -365,17 +349,27 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
configuredFolders = [{ uri: folder.toString() }];
|
||||
}
|
||||
|
||||
return Promise.resolve(new Workspace(singleFolder.id, toWorkspaceFolders(configuredFolders)));
|
||||
const workspace = new Workspace(singleFolder.id, toWorkspaceFolders(configuredFolders));
|
||||
this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is single folder.
|
||||
return Promise.resolve(workspace);
|
||||
}
|
||||
|
||||
private createEmptyWorkspace(emptyWorkspace: IEmptyWorkspaceInitializationPayload): Promise<Workspace> {
|
||||
return Promise.resolve(new Workspace(emptyWorkspace.id));
|
||||
const workspace = new Workspace(emptyWorkspace.id);
|
||||
this.releaseWorkspaceBarrier(); // Release barrier as workspace is complete because it is an empty workspace.
|
||||
return Promise.resolve(workspace);
|
||||
}
|
||||
|
||||
private releaseWorkspaceBarrier(): void {
|
||||
if (!this.completeWorkspaceBarrier.isOpen()) {
|
||||
this.completeWorkspaceBarrier.open();
|
||||
}
|
||||
}
|
||||
|
||||
private updateWorkspaceAndInitializeConfiguration(workspace: Workspace, postInitialisationTask: () => void): Promise<void> {
|
||||
const hasWorkspaceBefore = !!this.workspace;
|
||||
let previousState: WorkbenchState;
|
||||
let previousWorkspacePath: string;
|
||||
let previousWorkspacePath: string | undefined;
|
||||
let previousFolders: WorkspaceFolder[];
|
||||
|
||||
if (hasWorkspaceBefore) {
|
||||
@@ -467,7 +461,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
folderConfigurations.forEach((folderConfiguration, index) => folderConfigurationModels.set(folders[index].uri, folderConfiguration));
|
||||
|
||||
const currentConfiguration = this._configuration;
|
||||
this._configuration = new Configuration(this.defaultConfiguration, userConfigurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), this.getWorkbenchState() !== WorkbenchState.EMPTY ? this.workspace : null); //TODO: Sandy Avoid passing null
|
||||
this._configuration = new Configuration(this.defaultConfiguration, userConfigurationModel, workspaceConfiguration, folderConfigurationModels, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), this.workspace);
|
||||
|
||||
if (currentConfiguration) {
|
||||
const changedKeys = this._configuration.compare(currentConfiguration);
|
||||
@@ -495,10 +489,10 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
if (this.workspace && this._configuration) {
|
||||
this._configuration.updateDefaultConfiguration(this.defaultConfiguration);
|
||||
if (this.getWorkbenchState() === WorkbenchState.FOLDER) {
|
||||
this._configuration.updateWorkspaceConfiguration(this.cachedFolderConfigs.get(this.workspace.folders[0].uri).reprocess());
|
||||
this._configuration.updateWorkspaceConfiguration(this.cachedFolderConfigs.get(this.workspace.folders[0].uri)!.reprocess());
|
||||
} else {
|
||||
this._configuration.updateWorkspaceConfiguration(this.workspaceConfiguration.reprocessWorkspaceSettings());
|
||||
this.workspace.folders.forEach(folder => this._configuration.updateFolderConfiguration(folder.uri, this.cachedFolderConfigs.get(folder.uri).reprocess()));
|
||||
this.workspace.folders.forEach(folder => this._configuration.updateFolderConfiguration(folder.uri, this.cachedFolderConfigs.get(folder.uri)!.reprocess()));
|
||||
}
|
||||
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(keys), ConfigurationTarget.DEFAULT);
|
||||
}
|
||||
@@ -578,7 +572,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
for (const key of this.cachedFolderConfigs.keys()) {
|
||||
if (!this.workspace.folders.filter(folder => folder.uri.toString() === key.toString())[0]) {
|
||||
const folderConfiguration = this.cachedFolderConfigs.get(key);
|
||||
folderConfiguration.dispose();
|
||||
folderConfiguration!.dispose();
|
||||
this.cachedFolderConfigs.delete(key);
|
||||
changeEvent = changeEvent.change(this._configuration.compareAndDeleteFolderConfiguration(key));
|
||||
}
|
||||
@@ -609,14 +603,14 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
})]);
|
||||
}
|
||||
|
||||
private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides, donotNotifyError: boolean): Promise<void> {
|
||||
private writeConfigurationValue(key: string, value: any, target: ConfigurationTarget, overrides: IConfigurationOverrides | undefined, donotNotifyError: boolean): Promise<void> {
|
||||
if (target === ConfigurationTarget.DEFAULT) {
|
||||
return Promise.reject(new Error('Invalid configuration target'));
|
||||
}
|
||||
|
||||
if (target === ConfigurationTarget.MEMORY) {
|
||||
this._configuration.updateValue(key, value, overrides);
|
||||
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(overrides.overrideIdentifier ? [keyFromOverrideIdentifier(overrides.overrideIdentifier)] : [key], overrides.resource), target);
|
||||
this.triggerConfigurationChange(new ConfigurationChangeEvent().change(overrides && overrides.overrideIdentifier ? [keyFromOverrideIdentifier(overrides.overrideIdentifier)] : [key], overrides && overrides.resource || undefined), target);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -624,20 +618,20 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat
|
||||
.then(() => {
|
||||
switch (target) {
|
||||
case ConfigurationTarget.USER:
|
||||
return this.reloadUserConfiguration();
|
||||
return this.reloadUserConfiguration().then(_ => Promise.resolve());
|
||||
case ConfigurationTarget.WORKSPACE:
|
||||
return this.reloadWorkspaceConfiguration();
|
||||
case ConfigurationTarget.WORKSPACE_FOLDER:
|
||||
const workspaceFolder = overrides && overrides.resource ? this.workspace.getFolder(overrides.resource) : null;
|
||||
if (workspaceFolder) {
|
||||
return this.reloadWorkspaceFolderConfiguration(this.workspace.getFolder(overrides.resource), key).then(() => null);
|
||||
return this.reloadWorkspaceFolderConfiguration(workspaceFolder, key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
private deriveConfigurationTarget(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): ConfigurationTarget {
|
||||
private deriveConfigurationTarget(key: string, value: any, overrides: IConfigurationOverrides | undefined, target: ConfigurationTarget): ConfigurationTarget | undefined {
|
||||
if (target) {
|
||||
return target;
|
||||
}
|
||||
@@ -688,7 +682,7 @@ interface IExportedConfigurationNode {
|
||||
name: string;
|
||||
description: string;
|
||||
default: any;
|
||||
type: string | string[];
|
||||
type?: string | string[];
|
||||
enum?: any[];
|
||||
enumDescriptions?: string[];
|
||||
}
|
||||
@@ -696,8 +690,8 @@ interface IExportedConfigurationNode {
|
||||
interface IConfigurationExport {
|
||||
settings: IExportedConfigurationNode[];
|
||||
buildTime: number;
|
||||
commit: string;
|
||||
buildNumber: number;
|
||||
commit?: string;
|
||||
buildNumber?: number;
|
||||
}
|
||||
|
||||
export class DefaultConfigurationExportHelper {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { FolderSettingsModelParser, WorkspaceConfigurationChangeEvent, StandaloneConfigurationModelParser, AllKeysConfigurationChangeEvent, Configuration } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as sinon from 'sinon';
|
||||
import * as assert from 'assert';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as fs from 'fs';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
@@ -20,8 +20,8 @@ import { TestNotificationService } from 'vs/platform/notification/test/common/te
|
||||
import * as uuid from 'vs/base/common/uuid';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
|
||||
import { FileService } from 'vs/workbench/services/files/electron-browser/fileService';
|
||||
import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import { FileService } from 'vs/workbench/services/files/node/fileService';
|
||||
import { ConfigurationEditingService, ConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditingService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import * as sinon from 'sinon';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as os from 'os';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
@@ -18,23 +18,25 @@ import * as uuid from 'vs/base/common/uuid';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
|
||||
import { ISingleFolderWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/node/configurationEditingService';
|
||||
import { ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditingService';
|
||||
import { IFileService, FileChangesEvent, FileChangeType } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationTarget, IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
|
||||
import { workbenchInstantiationService, TestTextResourceConfigurationService, TestTextFileService, TestLifecycleService, TestEnvironmentService, TestStorageService } from 'vs/workbench/test/workbenchTestServices';
|
||||
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
|
||||
import { FileService } from 'vs/workbench/services/files/electron-browser/fileService';
|
||||
import { FileService } from 'vs/workbench/services/files/node/fileService';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
|
||||
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { Uri } from 'vscode';
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
|
||||
import { createHash } from 'crypto';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { originalFSPath } from 'vs/base/common/resources';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IWorkspaceIdentifier } from 'vs/workbench/services/configuration/node/configuration';
|
||||
|
||||
class SettingsTestEnvironmentService extends EnvironmentService {
|
||||
|
||||
@@ -58,14 +60,14 @@ function setUpFolder(folderName: string, parentDir: string): Promise<string> {
|
||||
return Promise.resolve(pfs.mkdirp(workspaceSettingsDir, 493).then(() => folderDir));
|
||||
}
|
||||
|
||||
function convertToWorkspacePayload(folder: Uri): ISingleFolderWorkspaceInitializationPayload {
|
||||
function convertToWorkspacePayload(folder: URI): ISingleFolderWorkspaceInitializationPayload {
|
||||
return {
|
||||
id: createHash('md5').update(folder.fsPath).digest('hex'),
|
||||
folder
|
||||
} as ISingleFolderWorkspaceInitializationPayload;
|
||||
}
|
||||
|
||||
function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: string }> {
|
||||
function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configPath: URI }> {
|
||||
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
@@ -77,7 +79,7 @@ function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configP
|
||||
fs.writeFileSync(configPath, JSON.stringify(workspace, null, '\t'));
|
||||
|
||||
return Promise.all(folders.map(folder => setUpFolder(folder, parentDir)))
|
||||
.then(() => ({ parentDir, configPath }));
|
||||
.then(() => ({ parentDir, configPath: URI.file(configPath) }));
|
||||
}));
|
||||
|
||||
}
|
||||
@@ -89,3 +91,19 @@ suite('WorkspaceContextService - Folder', () => {
|
||||
assert.equal(0, 0);
|
||||
});
|
||||
});
|
||||
|
||||
function getWorkspaceId(configPath: URI): string {
|
||||
let workspaceConfigPath = configPath.scheme === Schemas.file ? originalFSPath(configPath) : configPath.toString();
|
||||
if (!isLinux) {
|
||||
workspaceConfigPath = workspaceConfigPath.toLowerCase(); // sanitize for platform file system
|
||||
}
|
||||
|
||||
return createHash('md5').update(workspaceConfigPath).digest('hex');
|
||||
}
|
||||
|
||||
export function getWorkspaceIdentifier(configPath: URI): IWorkspaceIdentifier {
|
||||
return {
|
||||
configPath,
|
||||
id: getWorkspaceId(configPath)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user