提交 5ec65bdc 编写于 作者: B Benjamin Pasero

backup - remove discardAllBackups() method

This method is actually deleting the entire backup home
folder for the workspace and it is possible that this could
lead to race conditions when a backup is running at the same
time.
上级 9bec0160
......@@ -182,15 +182,14 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont
return true; // veto (save failed or was canceled)
}
return this.noVeto(dirtyCount === workingCopies.length ? true /* all */ : workingCopies); // no veto (dirty saved)
return this.noVeto(workingCopies); // no veto (dirty saved)
}
// Don't Save
else if (confirm === ConfirmResult.DONT_SAVE) {
const dirtyCount = this.workingCopyService.dirtyCount;
await this.doRevertAllBeforeShutdown(workingCopies);
return this.noVeto(dirtyCount === workingCopies.length ? true /* all */ : workingCopies); // no veto (dirty reverted)
return this.noVeto(workingCopies); // no veto (dirty reverted)
}
// Cancel
......@@ -243,7 +242,7 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont
}
}
private noVeto(backupsToDiscardOrAll: IWorkingCopy[] | boolean): boolean | Promise<boolean> {
private noVeto(backupsToDiscard: IWorkingCopy[]): boolean | Promise<boolean> {
if (this.lifecycleService.phase < LifecyclePhase.Restored) {
return false; // if editors have not restored, we are not up to speed with backups and thus should not discard them
}
......@@ -252,16 +251,6 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont
return false; // extension development does not track any backups
}
if (backupsToDiscardOrAll === true) {
// discard all backups
return this.backupFileService.discardAllBackups().then(() => false, () => false);
}
if (Array.isArray(backupsToDiscardOrAll)) {
// otherwise, discard individually
return Promise.all(backupsToDiscardOrAll.map(workingCopy => this.backupFileService.discardBackup(workingCopy.resource))).then(() => false, () => false);
}
return false;
return Promise.all(backupsToDiscard.map(workingCopy => this.backupFileService.discardBackup(workingCopy.resource))).then(() => false, () => false);
}
}
......@@ -279,11 +279,11 @@ suite('BackupTracker', () => {
let veto = event.value;
if (typeof veto === 'boolean') {
assert.ok(accessor.backupFileService.didDiscardAllBackups);
assert.ok(accessor.backupFileService.discardedBackups.length > 0);
assert.ok(!veto);
} else {
veto = await veto;
assert.ok(accessor.backupFileService.didDiscardAllBackups);
assert.ok(accessor.backupFileService.discardedBackups.length > 0);
assert.ok(!veto);
}
......@@ -452,7 +452,7 @@ suite('BackupTracker', () => {
accessor.lifecycleService.fireWillShutdown(event);
const veto = await (<Promise<boolean>>event.value);
assert.ok(!accessor.backupFileService.didDiscardAllBackups); // When hot exit is set, backups should never be cleaned since the confirm result is cancel
assert.equal(accessor.backupFileService.discardedBackups.length, 0); // When hot exit is set, backups should never be cleaned since the confirm result is cancel
assert.equal(veto, shouldVeto);
part.dispose();
......
......@@ -68,9 +68,4 @@ export interface IBackupFileService {
* @param resource The resource whose backup is being discarded discard to back up.
*/
discardBackup(resource: URI): Promise<void>;
/**
* Discards all backups that exist.
*/
discardAllBackups(): Promise<void>;
}
......@@ -163,10 +163,6 @@ export class BackupFileService implements IBackupFileService {
return this.impl.discardBackup(resource);
}
discardAllBackups(): Promise<void> {
return this.impl.discardAllBackups();
}
getBackups(): Promise<URI[]> {
return this.impl.getBackups();
}
......@@ -277,21 +273,6 @@ class BackupFileServiceImpl extends Disposable implements IBackupFileService {
});
}
async discardAllBackups(): Promise<void> {
// Discard each backup and clear model
// We go through the doDiscardBackup()
// method to benefit from the IO queue
const model = await this.ready;
await Promise.all(model.get().map(backupResource => this.doDiscardBackup(backupResource)));
model.clear();
// Delete the backup home for this workspace
// It will automatically be populated again
// once another backup is made
await this.deleteIgnoreFileNotFound(this.backupWorkspacePath);
}
private async deleteIgnoreFileNotFound(resource: URI): Promise<void> {
try {
await this.fileService.del(resource, { recursive: true });
......@@ -443,10 +424,6 @@ export class InMemoryBackupFileService implements IBackupFileService {
this.backups.delete(this.toBackupResource(resource).toString());
}
async discardAllBackups(): Promise<void> {
this.backups.clear();
}
toBackupResource(resource: URI): URI {
return URI.file(join(resource.scheme, this.hashPath(resource)));
}
......
......@@ -42,7 +42,6 @@ const barFile = URI.file(platform.isWindows ? 'c:\\Bar' : '/Bar');
const fooBarFile = URI.file(platform.isWindows ? 'c:\\Foo Bar' : '/Foo Bar');
const untitledFile = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' });
const fooBackupPath = path.join(workspaceBackupPath, 'file', hashPath(fooFile));
const barBackupPath = path.join(workspaceBackupPath, 'file', hashPath(barFile));
const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', hashPath(untitledFile));
class TestBackupEnvironmentService extends NativeWorkbenchEnvironmentService {
......@@ -58,6 +57,7 @@ export class NodeTestBackupFileService extends BackupFileService {
private backupResourceJoiners: Function[];
private discardBackupJoiners: Function[];
discardedBackups: URI[];
constructor(workspaceBackupPath: string) {
const environmentService = new TestBackupEnvironmentService(workspaceBackupPath);
......@@ -71,7 +71,7 @@ export class NodeTestBackupFileService extends BackupFileService {
this.fileService = fileService;
this.backupResourceJoiners = [];
this.discardBackupJoiners = [];
this.didDiscardAllBackups = false;
this.discardedBackups = [];
}
joinBackupResource(): Promise<void> {
......@@ -92,19 +92,12 @@ export class NodeTestBackupFileService extends BackupFileService {
async discardBackup(resource: URI): Promise<void> {
await super.discardBackup(resource);
this.discardedBackups.push(resource);
while (this.discardBackupJoiners.length) {
this.discardBackupJoiners.pop()!();
}
}
didDiscardAllBackups: boolean;
discardAllBackups(): Promise<void> {
this.didDiscardAllBackups = true;
return super.discardAllBackups();
}
}
suite('BackupFileService', () => {
......@@ -282,27 +275,6 @@ suite('BackupFileService', () => {
});
});
suite('discardAllBackups', () => {
test('text file', async () => {
await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false));
assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 1);
await service.backup(barFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false));
assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'file')).length, 2);
await service.discardAllBackups();
assert.equal(fs.existsSync(fooBackupPath), false);
assert.equal(fs.existsSync(barBackupPath), false);
assert.equal(fs.existsSync(path.join(workspaceBackupPath, 'file')), false);
});
test('untitled file', async () => {
await service.backup(untitledFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false));
assert.equal(fs.readdirSync(path.join(workspaceBackupPath, 'untitled')).length, 1);
await service.discardAllBackups();
assert.equal(fs.existsSync(untitledBackupPath), false);
assert.equal(fs.existsSync(path.join(workspaceBackupPath, 'untitled')), false);
});
});
suite('getBackups', () => {
test('("file") - text file', async () => {
await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false));
......
......@@ -1209,10 +1209,6 @@ export class TestBackupFileService implements IBackupFileService {
discardBackup(_resource: URI): Promise<void> {
return Promise.resolve();
}
discardAllBackups(): Promise<void> {
return Promise.resolve();
}
}
export class TestCodeEditorService implements ICodeEditorService {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册