提交 72950f8b 编写于 作者: B Benjamin Pasero

backup - wire in cancellation token to implementation

上级 29d459b6
...@@ -128,7 +128,7 @@ export abstract class BackupTracker extends Disposable { ...@@ -128,7 +128,7 @@ export abstract class BackupTracker extends Disposable {
if (workingCopy.isDirty()) { if (workingCopy.isDirty()) {
this.logService.trace(`[backup tracker] storing backup`, workingCopy.resource.toString()); this.logService.trace(`[backup tracker] storing backup`, workingCopy.resource.toString());
await this.backupFileService.backup(workingCopy.resource, backup.content, this.getContentVersion(workingCopy), backup.meta); await this.backupFileService.backup(workingCopy.resource, backup.content, this.getContentVersion(workingCopy), backup.meta, cts.token);
} }
} catch (error) { } catch (error) {
this.logService.error(error); this.logService.error(error);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ITextBufferFactory, ITextSnapshot } from 'vs/editor/common/model'; import { ITextBufferFactory, ITextSnapshot } from 'vs/editor/common/model';
import { CancellationToken } from 'vs/base/common/cancellation';
export const IBackupFileService = createDecorator<IBackupFileService>('backupFileService'); export const IBackupFileService = createDecorator<IBackupFileService>('backupFileService');
...@@ -59,8 +60,9 @@ export interface IBackupFileService { ...@@ -59,8 +60,9 @@ export interface IBackupFileService {
* @param versionId The optionsl version id of the resource to backup. * @param versionId The optionsl version id of the resource to backup.
* @param meta The optional meta data of the resource to backup. This information * @param meta The optional meta data of the resource to backup. This information
* can be restored later when loading the backup again. * can be restored later when loading the backup again.
* @param token The optional cancellation token if the operation can be cancelled.
*/ */
backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T): Promise<void>; backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T, token?: CancellationToken): Promise<void>;
/** /**
* Discards the backup associated with a resource if it exists. * Discards the backup associated with a resource if it exists.
......
...@@ -21,6 +21,7 @@ import { VSBuffer } from 'vs/base/common/buffer'; ...@@ -21,6 +21,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { TextSnapshotReadable, stringToSnapshot } from 'vs/workbench/services/textfile/common/textfiles'; import { TextSnapshotReadable, stringToSnapshot } from 'vs/workbench/services/textfile/common/textfiles';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { CancellationToken } from 'vs/base/common/cancellation';
export interface IBackupFilesModel { export interface IBackupFilesModel {
resolve(backupRoot: URI): Promise<IBackupFilesModel>; resolve(backupRoot: URI): Promise<IBackupFilesModel>;
...@@ -157,8 +158,8 @@ export class BackupFileService implements IBackupFileService { ...@@ -157,8 +158,8 @@ export class BackupFileService implements IBackupFileService {
return this.impl.hasBackupSync(resource, versionId); return this.impl.hasBackupSync(resource, versionId);
} }
backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T): Promise<void> { backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T, token?: CancellationToken): Promise<void> {
return this.impl.backup(resource, content, versionId, meta); return this.impl.backup(resource, content, versionId, meta, token);
} }
discardBackup(resource: URI): Promise<void> { discardBackup(resource: URI): Promise<void> {
...@@ -232,8 +233,11 @@ class BackupFileServiceImpl extends Disposable implements IBackupFileService { ...@@ -232,8 +233,11 @@ class BackupFileServiceImpl extends Disposable implements IBackupFileService {
return this.model.has(backupResource, versionId); return this.model.has(backupResource, versionId);
} }
async backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T): Promise<void> { async backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T, token?: CancellationToken): Promise<void> {
const model = await this.ready; const model = await this.ready;
if (token?.isCancellationRequested) {
return;
}
const backupResource = this.toBackupResource(resource); const backupResource = this.toBackupResource(resource);
if (model.has(backupResource, versionId, meta)) { if (model.has(backupResource, versionId, meta)) {
...@@ -241,6 +245,10 @@ class BackupFileServiceImpl extends Disposable implements IBackupFileService { ...@@ -241,6 +245,10 @@ class BackupFileServiceImpl extends Disposable implements IBackupFileService {
} }
return this.ioOperationQueues.queueFor(backupResource).queue(async () => { return this.ioOperationQueues.queueFor(backupResource).queue(async () => {
if (token?.isCancellationRequested) {
return;
}
let preamble: string | undefined = undefined; let preamble: string | undefined = undefined;
// With Metadata: URI + META-START + Meta + END // With Metadata: URI + META-START + Meta + END
...@@ -419,7 +427,7 @@ export class InMemoryBackupFileService implements IBackupFileService { ...@@ -419,7 +427,7 @@ export class InMemoryBackupFileService implements IBackupFileService {
return this.backups.has(backupResource.toString()); return this.backups.has(backupResource.toString());
} }
async backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T): Promise<void> { async backup<T extends object>(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: T, token?: CancellationToken): Promise<void> {
const backupResource = this.toBackupResource(resource); const backupResource = this.toBackupResource(resource);
this.backups.set(backupResource.toString(), content || stringToSnapshot('')); this.backups.set(backupResource.toString(), content || stringToSnapshot(''));
} }
......
...@@ -28,6 +28,7 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file ...@@ -28,6 +28,7 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file
import { VSBuffer } from 'vs/base/common/buffer'; import { VSBuffer } from 'vs/base/common/buffer';
import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices';
import { TestProductService } from 'vs/workbench/test/browser/workbenchTestServices'; import { TestProductService } from 'vs/workbench/test/browser/workbenchTestServices';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice'); const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice');
const backupHome = path.join(userdataDir, 'Backups'); const backupHome = path.join(userdataDir, 'Backups');
...@@ -80,8 +81,8 @@ export class NodeTestBackupFileService extends BackupFileService { ...@@ -80,8 +81,8 @@ export class NodeTestBackupFileService extends BackupFileService {
return new Promise(resolve => this.backupResourceJoiners.push(resolve)); return new Promise(resolve => this.backupResourceJoiners.push(resolve));
} }
async backup(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: any): Promise<void> { async backup(resource: URI, content?: ITextSnapshot, versionId?: number, meta?: any, token?: CancellationToken): Promise<void> {
await super.backup(resource, content, versionId, meta); await super.backup(resource, content, versionId, meta, token);
while (this.backupResourceJoiners.length) { while (this.backupResourceJoiners.length) {
this.backupResourceJoiners.pop()!(); this.backupResourceJoiners.pop()!();
...@@ -262,6 +263,16 @@ suite('BackupFileService', () => { ...@@ -262,6 +263,16 @@ suite('BackupFileService', () => {
model.dispose(); model.dispose();
}); });
test('cancellation', async () => {
const cts = new CancellationTokenSource();
const promise = service.backup(fooFile, undefined, undefined, undefined, cts.token);
cts.cancel();
await promise;
assert.equal(fs.existsSync(fooBackupPath), false);
assert.ok(!service.hasBackupSync(fooFile));
});
}); });
suite('discardBackup', () => { suite('discardBackup', () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册