mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-30 17:23:29 -05:00
Merge vscode 1.67 (#20883)
* Fix initial build breaks from 1.67 merge (#2514) * Update yarn lock files * Update build scripts * Fix tsconfig * Build breaks * WIP * Update yarn lock files * Misc breaks * Updates to package.json * Breaks * Update yarn * Fix breaks * Breaks * Build breaks * Breaks * Breaks * Breaks * Breaks * Breaks * Missing file * Breaks * Breaks * Breaks * Breaks * Breaks * Fix several runtime breaks (#2515) * Missing files * Runtime breaks * Fix proxy ordering issue * Remove commented code * Fix breaks with opening query editor * Fix post merge break * Updates related to setup build and other breaks (#2516) * Fix bundle build issues * Update distro * Fix distro merge and update build JS files * Disable pipeline steps * Remove stats call * Update license name * Make new RPM dependencies a warning * Fix extension manager version checks * Update JS file * Fix a few runtime breaks * Fixes * Fix runtime issues * Fix build breaks * Update notebook tests (part 1) * Fix broken tests * Linting errors * Fix hygiene * Disable lint rules * Bump distro * Turn off smoke tests * Disable integration tests * Remove failing "activate" test * Remove failed test assertion * Disable other broken test * Disable query history tests * Disable extension unit tests * Disable failing tasks
This commit is contained in:
123
src/vs/platform/userData/common/fileUserDataProvider.ts
Normal file
123
src/vs/platform/userData/common/fileUserDataProvider.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IFileSystemProviderWithFileReadWriteCapability, IFileChange, IWatchOptions, IStat, IFileOverwriteOptions, FileType, IFileWriteOptions, IFileDeleteOptions, FileSystemProviderCapabilities, IFileSystemProviderWithFileReadStreamCapability, IFileReadStreamOptions, IFileSystemProviderWithFileAtomicReadCapability } from 'vs/platform/files/common/files';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { newWriteableStream, ReadableStreamEvents } from 'vs/base/common/stream';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
/**
|
||||
* This is a wrapper on top of the local filesystem provider which will
|
||||
* - Convert the user data resources to file system scheme and vice-versa
|
||||
* - Enforces atomic reads for user data
|
||||
*/
|
||||
export class FileUserDataProvider extends Disposable implements
|
||||
IFileSystemProviderWithFileReadWriteCapability,
|
||||
IFileSystemProviderWithFileReadStreamCapability,
|
||||
IFileSystemProviderWithFileAtomicReadCapability {
|
||||
|
||||
get capabilities() { return this.fileSystemProvider.capabilities & ~FileSystemProviderCapabilities.FileOpenReadWriteClose; }
|
||||
readonly onDidChangeCapabilities: Event<void> = this.fileSystemProvider.onDidChangeCapabilities;
|
||||
|
||||
private readonly _onDidChangeFile = this._register(new Emitter<readonly IFileChange[]>());
|
||||
readonly onDidChangeFile: Event<readonly IFileChange[]> = this._onDidChangeFile.event;
|
||||
|
||||
private readonly watchResources = TernarySearchTree.forUris<URI>(() => !(this.capabilities & FileSystemProviderCapabilities.PathCaseSensitive));
|
||||
|
||||
constructor(
|
||||
private readonly fileSystemScheme: string,
|
||||
private readonly fileSystemProvider: IFileSystemProviderWithFileReadWriteCapability & (IFileSystemProviderWithFileReadStreamCapability | IFileSystemProviderWithFileAtomicReadCapability),
|
||||
private readonly userDataScheme: string,
|
||||
private readonly logService: ILogService,
|
||||
) {
|
||||
super();
|
||||
this._register(this.fileSystemProvider.onDidChangeFile(e => this.handleFileChanges(e)));
|
||||
}
|
||||
|
||||
watch(resource: URI, opts: IWatchOptions): IDisposable {
|
||||
this.watchResources.set(resource, resource);
|
||||
const disposable = this.fileSystemProvider.watch(this.toFileSystemResource(resource), opts);
|
||||
return toDisposable(() => {
|
||||
this.watchResources.delete(resource);
|
||||
disposable.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
stat(resource: URI): Promise<IStat> {
|
||||
return this.fileSystemProvider.stat(this.toFileSystemResource(resource));
|
||||
}
|
||||
|
||||
mkdir(resource: URI): Promise<void> {
|
||||
return this.fileSystemProvider.mkdir(this.toFileSystemResource(resource));
|
||||
}
|
||||
|
||||
rename(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void> {
|
||||
return this.fileSystemProvider.rename(this.toFileSystemResource(from), this.toFileSystemResource(to), opts);
|
||||
}
|
||||
|
||||
readFile(resource: URI): Promise<Uint8Array> {
|
||||
return this.fileSystemProvider.readFile(this.toFileSystemResource(resource), { atomic: true });
|
||||
}
|
||||
|
||||
readFileStream(resource: URI, opts: IFileReadStreamOptions, token: CancellationToken): ReadableStreamEvents<Uint8Array> {
|
||||
const stream = newWriteableStream<Uint8Array>(data => VSBuffer.concat(data.map(data => VSBuffer.wrap(data))).buffer);
|
||||
(async () => {
|
||||
try {
|
||||
const contents = await this.readFile(resource);
|
||||
stream.end(contents);
|
||||
} catch (error) {
|
||||
stream.error(error);
|
||||
stream.end();
|
||||
}
|
||||
})();
|
||||
return stream;
|
||||
}
|
||||
|
||||
readdir(resource: URI): Promise<[string, FileType][]> {
|
||||
return this.fileSystemProvider.readdir(this.toFileSystemResource(resource));
|
||||
}
|
||||
|
||||
writeFile(resource: URI, content: Uint8Array, opts: IFileWriteOptions): Promise<void> {
|
||||
return this.fileSystemProvider.writeFile(this.toFileSystemResource(resource), content, opts);
|
||||
}
|
||||
|
||||
delete(resource: URI, opts: IFileDeleteOptions): Promise<void> {
|
||||
return this.fileSystemProvider.delete(this.toFileSystemResource(resource), opts);
|
||||
}
|
||||
|
||||
private handleFileChanges(changes: readonly IFileChange[]): void {
|
||||
const userDataChanges: IFileChange[] = [];
|
||||
for (const change of changes) {
|
||||
if (change.resource.scheme !== this.fileSystemScheme) {
|
||||
continue; // only interested in file schemes
|
||||
}
|
||||
|
||||
const userDataResource = this.toUserDataResource(change.resource);
|
||||
if (this.watchResources.findSubstr(userDataResource)) {
|
||||
userDataChanges.push({
|
||||
resource: userDataResource,
|
||||
type: change.type
|
||||
});
|
||||
}
|
||||
}
|
||||
if (userDataChanges.length) {
|
||||
this.logService.debug('User data changed');
|
||||
this._onDidChangeFile.fire(userDataChanges);
|
||||
}
|
||||
}
|
||||
|
||||
private toFileSystemResource(userDataResource: URI): URI {
|
||||
return userDataResource.with({ scheme: this.fileSystemScheme });
|
||||
}
|
||||
|
||||
private toUserDataResource(fileSystemResource: URI): URI {
|
||||
return fileSystemResource.with({ scheme: this.userDataScheme });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,435 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { IFileService, FileChangeType, IFileChange, IFileSystemProviderWithFileReadWriteCapability, IStat, FileType, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { FileUserDataProvider } from 'vs/platform/userData/common/fileUserDataProvider';
|
||||
import { dirname, isEqual, joinPath } from 'vs/base/common/resources';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { DisposableStore, IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
|
||||
import { AbstractNativeEnvironmentService } from 'vs/platform/environment/common/environmentService';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
|
||||
const ROOT = URI.file('tests').with({ scheme: 'vscode-tests' });
|
||||
|
||||
class TestEnvironmentService extends AbstractNativeEnvironmentService {
|
||||
constructor(private readonly _appSettingsHome: URI) {
|
||||
super(Object.create(null), Object.create(null), { _serviceBrand: undefined, ...product });
|
||||
}
|
||||
override get userRoamingDataHome() { return this._appSettingsHome.with({ scheme: Schemas.vscodeUserData }); }
|
||||
}
|
||||
|
||||
suite('FileUserDataProvider', () => {
|
||||
|
||||
let testObject: IFileService;
|
||||
let userDataHomeOnDisk: URI;
|
||||
let backupWorkspaceHomeOnDisk: URI;
|
||||
let environmentService: IEnvironmentService;
|
||||
const disposables = new DisposableStore();
|
||||
let fileUserDataProvider: FileUserDataProvider;
|
||||
|
||||
setup(async () => {
|
||||
const logService = new NullLogService();
|
||||
testObject = disposables.add(new FileService(logService));
|
||||
const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider());
|
||||
disposables.add(testObject.registerProvider(ROOT.scheme, fileSystemProvider));
|
||||
|
||||
userDataHomeOnDisk = joinPath(ROOT, 'User');
|
||||
const backupHome = joinPath(ROOT, 'Backups');
|
||||
backupWorkspaceHomeOnDisk = joinPath(backupHome, 'workspaceId');
|
||||
await testObject.createFolder(userDataHomeOnDisk);
|
||||
await testObject.createFolder(backupWorkspaceHomeOnDisk);
|
||||
|
||||
environmentService = new TestEnvironmentService(userDataHomeOnDisk);
|
||||
|
||||
fileUserDataProvider = new FileUserDataProvider(ROOT.scheme, fileSystemProvider, Schemas.vscodeUserData, logService);
|
||||
disposables.add(fileUserDataProvider);
|
||||
disposables.add(testObject.registerProvider(Schemas.vscodeUserData, fileUserDataProvider));
|
||||
});
|
||||
|
||||
teardown(() => disposables.clear());
|
||||
|
||||
test('exists return false when file does not exist', async () => {
|
||||
const exists = await testObject.exists(environmentService.settingsResource);
|
||||
assert.strictEqual(exists, false);
|
||||
});
|
||||
|
||||
test('read file throws error if not exist', async () => {
|
||||
try {
|
||||
await testObject.readFile(environmentService.settingsResource);
|
||||
assert.fail('Should fail since file does not exist');
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
test('read existing file', async () => {
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString('{}'));
|
||||
const result = await testObject.readFile(environmentService.settingsResource);
|
||||
assert.strictEqual(result.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('create file', async () => {
|
||||
const resource = environmentService.settingsResource;
|
||||
const actual1 = await testObject.createFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'settings.json'));
|
||||
assert.strictEqual(actual2.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('write file creates the file if not exist', async () => {
|
||||
const resource = environmentService.settingsResource;
|
||||
const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'settings.json'));
|
||||
assert.strictEqual(actual2.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('write to existing file', async () => {
|
||||
const resource = environmentService.settingsResource;
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString('{}'));
|
||||
const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{a:1}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'settings.json'));
|
||||
assert.strictEqual(actual2.value.toString(), '{a:1}');
|
||||
});
|
||||
|
||||
test('delete file', async () => {
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString(''));
|
||||
await testObject.del(environmentService.settingsResource);
|
||||
const result = await testObject.exists(joinPath(userDataHomeOnDisk, 'settings.json'));
|
||||
assert.strictEqual(false, result);
|
||||
});
|
||||
|
||||
test('resolve file', async () => {
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString(''));
|
||||
const result = await testObject.resolve(environmentService.settingsResource);
|
||||
assert.ok(!result.isDirectory);
|
||||
assert.ok(result.children === undefined);
|
||||
});
|
||||
|
||||
test('exists return false for folder that does not exist', async () => {
|
||||
const exists = await testObject.exists(environmentService.snippetsHome);
|
||||
assert.strictEqual(exists, false);
|
||||
});
|
||||
|
||||
test('exists return true for folder that exists', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
const exists = await testObject.exists(environmentService.snippetsHome);
|
||||
assert.strictEqual(exists, true);
|
||||
});
|
||||
|
||||
test('read file throws error for folder', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
try {
|
||||
await testObject.readFile(environmentService.snippetsHome);
|
||||
assert.fail('Should fail since read file is not supported for folders');
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
test('read file under folder', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}'));
|
||||
const resource = joinPath(environmentService.snippetsHome, 'settings.json');
|
||||
const actual = await testObject.readFile(resource);
|
||||
assert.strictEqual(actual.resource.toString(), resource.toString());
|
||||
assert.strictEqual(actual.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('read file under sub folder', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets', 'java'));
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'java', 'settings.json'), VSBuffer.fromString('{}'));
|
||||
const resource = joinPath(environmentService.snippetsHome, 'java/settings.json');
|
||||
const actual = await testObject.readFile(resource);
|
||||
assert.strictEqual(actual.resource.toString(), resource.toString());
|
||||
assert.strictEqual(actual.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('create file under folder that exists', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
const resource = joinPath(environmentService.snippetsHome, 'settings.json');
|
||||
const actual1 = await testObject.createFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'));
|
||||
assert.strictEqual(actual2.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('create file under folder that does not exist', async () => {
|
||||
const resource = joinPath(environmentService.snippetsHome, 'settings.json');
|
||||
const actual1 = await testObject.createFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'));
|
||||
assert.strictEqual(actual2.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('write to not existing file under container that exists', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
const resource = joinPath(environmentService.snippetsHome, 'settings.json');
|
||||
const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'));
|
||||
assert.strictEqual(actual.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('write to not existing file under container that does not exists', async () => {
|
||||
const resource = joinPath(environmentService.snippetsHome, 'settings.json');
|
||||
const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'));
|
||||
assert.strictEqual(actual.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('write to existing file under container', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}'));
|
||||
const resource = joinPath(environmentService.snippetsHome, 'settings.json');
|
||||
const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{a:1}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'));
|
||||
assert.strictEqual(actual.value.toString(), '{a:1}');
|
||||
});
|
||||
|
||||
test('write file under sub container', async () => {
|
||||
const resource = joinPath(environmentService.snippetsHome, 'java/settings.json');
|
||||
const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}'));
|
||||
assert.strictEqual(actual1.resource.toString(), resource.toString());
|
||||
const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'java', 'settings.json'));
|
||||
assert.strictEqual(actual.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('delete throws error for folder that does not exist', async () => {
|
||||
try {
|
||||
await testObject.del(environmentService.snippetsHome);
|
||||
assert.fail('Should fail the folder does not exist');
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
test('delete not existing file under container that exists', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
try {
|
||||
await testObject.del(joinPath(environmentService.snippetsHome, 'settings.json'));
|
||||
assert.fail('Should fail since file does not exist');
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
test('delete not existing file under container that does not exists', async () => {
|
||||
try {
|
||||
await testObject.del(joinPath(environmentService.snippetsHome, 'settings.json'));
|
||||
assert.fail('Should fail since file does not exist');
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
test('delete existing file under folder', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}'));
|
||||
await testObject.del(joinPath(environmentService.snippetsHome, 'settings.json'));
|
||||
const exists = await testObject.exists(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'));
|
||||
assert.strictEqual(exists, false);
|
||||
});
|
||||
|
||||
test('resolve folder', async () => {
|
||||
await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets'));
|
||||
await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}'));
|
||||
const result = await testObject.resolve(environmentService.snippetsHome);
|
||||
assert.ok(result.isDirectory);
|
||||
assert.ok(result.children !== undefined);
|
||||
assert.strictEqual(result.children!.length, 1);
|
||||
assert.strictEqual(result.children![0].resource.toString(), joinPath(environmentService.snippetsHome, 'settings.json').toString());
|
||||
});
|
||||
|
||||
test('read backup file', async () => {
|
||||
await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'), VSBuffer.fromString('{}'));
|
||||
const result = await testObject.readFile(joinPath(backupWorkspaceHomeOnDisk.with({ scheme: environmentService.userRoamingDataHome.scheme }), `backup.json`));
|
||||
assert.strictEqual(result.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('create backup file', async () => {
|
||||
await testObject.createFile(joinPath(backupWorkspaceHomeOnDisk.with({ scheme: environmentService.userRoamingDataHome.scheme }), `backup.json`), VSBuffer.fromString('{}'));
|
||||
const result = await testObject.readFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'));
|
||||
assert.strictEqual(result.value.toString(), '{}');
|
||||
});
|
||||
|
||||
test('write backup file', async () => {
|
||||
await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'), VSBuffer.fromString('{}'));
|
||||
await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk.with({ scheme: environmentService.userRoamingDataHome.scheme }), `backup.json`), VSBuffer.fromString('{a:1}'));
|
||||
const result = await testObject.readFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'));
|
||||
assert.strictEqual(result.value.toString(), '{a:1}');
|
||||
});
|
||||
|
||||
test('resolve backups folder', async () => {
|
||||
await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'), VSBuffer.fromString('{}'));
|
||||
const result = await testObject.resolve(backupWorkspaceHomeOnDisk.with({ scheme: environmentService.userRoamingDataHome.scheme }));
|
||||
assert.ok(result.isDirectory);
|
||||
assert.ok(result.children !== undefined);
|
||||
assert.strictEqual(result.children!.length, 1);
|
||||
assert.strictEqual(result.children![0].resource.toString(), joinPath(backupWorkspaceHomeOnDisk.with({ scheme: environmentService.userRoamingDataHome.scheme }), `backup.json`).toString());
|
||||
});
|
||||
});
|
||||
|
||||
class TestFileSystemProvider implements IFileSystemProviderWithFileReadWriteCapability {
|
||||
|
||||
constructor(readonly onDidChangeFile: Event<readonly IFileChange[]>) { }
|
||||
|
||||
readonly capabilities: FileSystemProviderCapabilities = FileSystemProviderCapabilities.FileReadWrite;
|
||||
|
||||
readonly onDidChangeCapabilities: Event<void> = Event.None;
|
||||
|
||||
watch(): IDisposable { return Disposable.None; }
|
||||
|
||||
stat(): Promise<IStat> { throw new Error('Not Supported'); }
|
||||
|
||||
mkdir(resource: URI): Promise<void> { throw new Error('Not Supported'); }
|
||||
|
||||
rename(): Promise<void> { throw new Error('Not Supported'); }
|
||||
|
||||
readFile(resource: URI): Promise<Uint8Array> { throw new Error('Not Supported'); }
|
||||
|
||||
readdir(resource: URI): Promise<[string, FileType][]> { throw new Error('Not Supported'); }
|
||||
|
||||
writeFile(): Promise<void> { throw new Error('Not Supported'); }
|
||||
|
||||
delete(): Promise<void> { throw new Error('Not Supported'); }
|
||||
|
||||
}
|
||||
|
||||
suite('FileUserDataProvider - Watching', () => {
|
||||
|
||||
let testObject: FileUserDataProvider;
|
||||
const disposables = new DisposableStore();
|
||||
const rootFileResource = joinPath(ROOT, 'User');
|
||||
const rootUserDataResource = rootFileResource.with({ scheme: Schemas.vscodeUserData });
|
||||
|
||||
const fileEventEmitter: Emitter<readonly IFileChange[]> = new Emitter<readonly IFileChange[]>();
|
||||
disposables.add(fileEventEmitter);
|
||||
|
||||
setup(() => {
|
||||
testObject = disposables.add(new FileUserDataProvider(rootFileResource.scheme, new TestFileSystemProvider(fileEventEmitter.event), Schemas.vscodeUserData, new NullLogService()));
|
||||
});
|
||||
|
||||
teardown(() => disposables.clear());
|
||||
|
||||
test('file added change event', done => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const expected = joinPath(rootUserDataResource, 'settings.json');
|
||||
const target = joinPath(rootFileResource, 'settings.json');
|
||||
disposables.add(testObject.onDidChangeFile(e => {
|
||||
if (isEqual(e[0].resource, expected) && e[0].type === FileChangeType.ADDED) {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.ADDED
|
||||
}]);
|
||||
});
|
||||
|
||||
test('file updated change event', done => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const expected = joinPath(rootUserDataResource, 'settings.json');
|
||||
const target = joinPath(rootFileResource, 'settings.json');
|
||||
disposables.add(testObject.onDidChangeFile(e => {
|
||||
if (isEqual(e[0].resource, expected) && e[0].type === FileChangeType.UPDATED) {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.UPDATED
|
||||
}]);
|
||||
});
|
||||
|
||||
test('file deleted change event', done => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const expected = joinPath(rootUserDataResource, 'settings.json');
|
||||
const target = joinPath(rootFileResource, 'settings.json');
|
||||
disposables.add(testObject.onDidChangeFile(e => {
|
||||
if (isEqual(e[0].resource, expected) && e[0].type === FileChangeType.DELETED) {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.DELETED
|
||||
}]);
|
||||
});
|
||||
|
||||
test('file under folder created change event', done => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const expected = joinPath(rootUserDataResource, 'snippets', 'settings.json');
|
||||
const target = joinPath(rootFileResource, 'snippets', 'settings.json');
|
||||
disposables.add(testObject.onDidChangeFile(e => {
|
||||
if (isEqual(e[0].resource, expected) && e[0].type === FileChangeType.ADDED) {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.ADDED
|
||||
}]);
|
||||
});
|
||||
|
||||
test('file under folder updated change event', done => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const expected = joinPath(rootUserDataResource, 'snippets', 'settings.json');
|
||||
const target = joinPath(rootFileResource, 'snippets', 'settings.json');
|
||||
disposables.add(testObject.onDidChangeFile(e => {
|
||||
if (isEqual(e[0].resource, expected) && e[0].type === FileChangeType.UPDATED) {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.UPDATED
|
||||
}]);
|
||||
});
|
||||
|
||||
test('file under folder deleted change event', done => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const expected = joinPath(rootUserDataResource, 'snippets', 'settings.json');
|
||||
const target = joinPath(rootFileResource, 'snippets', 'settings.json');
|
||||
disposables.add(testObject.onDidChangeFile(e => {
|
||||
if (isEqual(e[0].resource, expected) && e[0].type === FileChangeType.DELETED) {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.DELETED
|
||||
}]);
|
||||
});
|
||||
|
||||
test('event is not triggered if not watched', async () => {
|
||||
const target = joinPath(rootFileResource, 'settings.json');
|
||||
let triggered = false;
|
||||
testObject.onDidChangeFile(() => triggered = true);
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.DELETED
|
||||
}]);
|
||||
if (triggered) {
|
||||
assert.fail('event should not be triggered');
|
||||
}
|
||||
});
|
||||
|
||||
test('event is not triggered if not watched 2', async () => {
|
||||
disposables.add(testObject.watch(rootUserDataResource, { excludes: [], recursive: false }));
|
||||
const target = joinPath(dirname(rootFileResource), 'settings.json');
|
||||
let triggered = false;
|
||||
testObject.onDidChangeFile(() => triggered = true);
|
||||
fileEventEmitter.fire([{
|
||||
resource: target,
|
||||
type: FileChangeType.DELETED
|
||||
}]);
|
||||
if (triggered) {
|
||||
assert.fail('event should not be triggered');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user