提交 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 ...@@ -182,15 +182,14 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont
return true; // veto (save failed or was canceled) 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 // Don't Save
else if (confirm === ConfirmResult.DONT_SAVE) { else if (confirm === ConfirmResult.DONT_SAVE) {
const dirtyCount = this.workingCopyService.dirtyCount;
await this.doRevertAllBeforeShutdown(workingCopies); 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 // Cancel
...@@ -243,7 +242,7 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont ...@@ -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) { 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 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 ...@@ -252,16 +251,6 @@ export class NativeBackupTracker extends BackupTracker implements IWorkbenchCont
return false; // extension development does not track any backups return false; // extension development does not track any backups
} }
if (backupsToDiscardOrAll === true) { return Promise.all(backupsToDiscard.map(workingCopy => this.backupFileService.discardBackup(workingCopy.resource))).then(() => false, () => false);
// 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;
} }
} }
...@@ -279,11 +279,11 @@ suite('BackupTracker', () => { ...@@ -279,11 +279,11 @@ suite('BackupTracker', () => {
let veto = event.value; let veto = event.value;
if (typeof veto === 'boolean') { if (typeof veto === 'boolean') {
assert.ok(accessor.backupFileService.didDiscardAllBackups); assert.ok(accessor.backupFileService.discardedBackups.length > 0);
assert.ok(!veto); assert.ok(!veto);
} else { } else {
veto = await veto; veto = await veto;
assert.ok(accessor.backupFileService.didDiscardAllBackups); assert.ok(accessor.backupFileService.discardedBackups.length > 0);
assert.ok(!veto); assert.ok(!veto);
} }
...@@ -452,7 +452,7 @@ suite('BackupTracker', () => { ...@@ -452,7 +452,7 @@ suite('BackupTracker', () => {
accessor.lifecycleService.fireWillShutdown(event); accessor.lifecycleService.fireWillShutdown(event);
const veto = await (<Promise<boolean>>event.value); 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); assert.equal(veto, shouldVeto);
part.dispose(); part.dispose();
......
...@@ -68,9 +68,4 @@ export interface IBackupFileService { ...@@ -68,9 +68,4 @@ export interface IBackupFileService {
* @param resource The resource whose backup is being discarded discard to back up. * @param resource The resource whose backup is being discarded discard to back up.
*/ */
discardBackup(resource: URI): Promise<void>; discardBackup(resource: URI): Promise<void>;
/**
* Discards all backups that exist.
*/
discardAllBackups(): Promise<void>;
} }
...@@ -163,10 +163,6 @@ export class BackupFileService implements IBackupFileService { ...@@ -163,10 +163,6 @@ export class BackupFileService implements IBackupFileService {
return this.impl.discardBackup(resource); return this.impl.discardBackup(resource);
} }
discardAllBackups(): Promise<void> {
return this.impl.discardAllBackups();
}
getBackups(): Promise<URI[]> { getBackups(): Promise<URI[]> {
return this.impl.getBackups(); return this.impl.getBackups();
} }
...@@ -277,21 +273,6 @@ class BackupFileServiceImpl extends Disposable implements IBackupFileService { ...@@ -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> { private async deleteIgnoreFileNotFound(resource: URI): Promise<void> {
try { try {
await this.fileService.del(resource, { recursive: true }); await this.fileService.del(resource, { recursive: true });
...@@ -443,10 +424,6 @@ export class InMemoryBackupFileService implements IBackupFileService { ...@@ -443,10 +424,6 @@ export class InMemoryBackupFileService implements IBackupFileService {
this.backups.delete(this.toBackupResource(resource).toString()); this.backups.delete(this.toBackupResource(resource).toString());
} }
async discardAllBackups(): Promise<void> {
this.backups.clear();
}
toBackupResource(resource: URI): URI { toBackupResource(resource: URI): URI {
return URI.file(join(resource.scheme, this.hashPath(resource))); return URI.file(join(resource.scheme, this.hashPath(resource)));
} }
......
...@@ -42,7 +42,6 @@ const barFile = URI.file(platform.isWindows ? 'c:\\Bar' : '/Bar'); ...@@ -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 fooBarFile = URI.file(platform.isWindows ? 'c:\\Foo Bar' : '/Foo Bar');
const untitledFile = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' }); const untitledFile = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' });
const fooBackupPath = path.join(workspaceBackupPath, 'file', hashPath(fooFile)); const fooBackupPath = path.join(workspaceBackupPath, 'file', hashPath(fooFile));
const barBackupPath = path.join(workspaceBackupPath, 'file', hashPath(barFile));
const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', hashPath(untitledFile)); const untitledBackupPath = path.join(workspaceBackupPath, 'untitled', hashPath(untitledFile));
class TestBackupEnvironmentService extends NativeWorkbenchEnvironmentService { class TestBackupEnvironmentService extends NativeWorkbenchEnvironmentService {
...@@ -58,6 +57,7 @@ export class NodeTestBackupFileService extends BackupFileService { ...@@ -58,6 +57,7 @@ export class NodeTestBackupFileService extends BackupFileService {
private backupResourceJoiners: Function[]; private backupResourceJoiners: Function[];
private discardBackupJoiners: Function[]; private discardBackupJoiners: Function[];
discardedBackups: URI[];
constructor(workspaceBackupPath: string) { constructor(workspaceBackupPath: string) {
const environmentService = new TestBackupEnvironmentService(workspaceBackupPath); const environmentService = new TestBackupEnvironmentService(workspaceBackupPath);
...@@ -71,7 +71,7 @@ export class NodeTestBackupFileService extends BackupFileService { ...@@ -71,7 +71,7 @@ export class NodeTestBackupFileService extends BackupFileService {
this.fileService = fileService; this.fileService = fileService;
this.backupResourceJoiners = []; this.backupResourceJoiners = [];
this.discardBackupJoiners = []; this.discardBackupJoiners = [];
this.didDiscardAllBackups = false; this.discardedBackups = [];
} }
joinBackupResource(): Promise<void> { joinBackupResource(): Promise<void> {
...@@ -92,19 +92,12 @@ export class NodeTestBackupFileService extends BackupFileService { ...@@ -92,19 +92,12 @@ export class NodeTestBackupFileService extends BackupFileService {
async discardBackup(resource: URI): Promise<void> { async discardBackup(resource: URI): Promise<void> {
await super.discardBackup(resource); await super.discardBackup(resource);
this.discardedBackups.push(resource);
while (this.discardBackupJoiners.length) { while (this.discardBackupJoiners.length) {
this.discardBackupJoiners.pop()!(); this.discardBackupJoiners.pop()!();
} }
} }
didDiscardAllBackups: boolean;
discardAllBackups(): Promise<void> {
this.didDiscardAllBackups = true;
return super.discardAllBackups();
}
} }
suite('BackupFileService', () => { suite('BackupFileService', () => {
...@@ -282,27 +275,6 @@ 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', () => { suite('getBackups', () => {
test('("file") - text file', async () => { test('("file") - text file', async () => {
await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false)); await service.backup(fooFile, createTextBufferFactory('test').create(DefaultEndOfLine.LF).createSnapshot(false));
......
...@@ -1209,10 +1209,6 @@ export class TestBackupFileService implements IBackupFileService { ...@@ -1209,10 +1209,6 @@ export class TestBackupFileService implements IBackupFileService {
discardBackup(_resource: URI): Promise<void> { discardBackup(_resource: URI): Promise<void> {
return Promise.resolve(); return Promise.resolve();
} }
discardAllBackups(): Promise<void> {
return Promise.resolve();
}
} }
export class TestCodeEditorService implements ICodeEditorService { export class TestCodeEditorService implements ICodeEditorService {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册